Reputation: 1529
I have a data frame for which I would like to complete the columns from left to right by using the lasted non NA value and adding (foo)
suffix after it. For example, this data frame:
df <- data.frame(
x = c("one", "one", "three"),
y = c("two", "four", NA),
z = c("three", NA, NA)
)
df
#> x y z
#> 1 one two three
#> 2 one four <NA>
#> 3 three <NA> <NA>
would produce:
data.frame(
x = c("one", "one", "three"),
y = c("two", "four", "three (foo)"),
z = c("three", "four (foo)", "three (foo)")
)
#> x y z
#> 1 one two three
#> 2 one four four (foo)
#> 3 three three (foo) three (foo)
Is there an elegant way to do it? It can be base R, tidyverse or data.table solution. Created on 2019-06-26 by the reprex package (v0.3.0)
Upvotes: 0
Views: 67
Reputation: 1044
Here is an approach using base
package and dplyr
:
library(dplyr)
df <- data.frame(
x = c("one", "one", "three"),
y = c("two", "four", NA),
z = c("three", NA, NA)
)
nalast = function(x){
l1 = x
nas = is.na(l1)
l1[nas] = paste0(x[tail(which(!nas),n=1)]," (foo)")
return(l1)
}
df2 = apply(X = df, MARGIN = 2, FUN = nalast)
df2
Wich gives
> df2
x y z
[1,] "one" "two" "three"
[2,] "one" "four" "three (foo)"
[3,] "three" "four (foo)" "three (foo)"
>
Upvotes: 1
Reputation: 51592
Here is a tidyverse
approach,
library(tidyverse)
df %>%
mutate(new = row_number()) %>%
gather(var, val, - new) %>%
group_by(new) %>%
mutate(flag = as.integer(is.na(val))) %>%
fill(val) %>%
mutate(val = replace(val, flag == 1, paste(val[flag == 1], '(foo)'))) %>%
select(-flag) %>%
spread(var, val)
which gives,
# A tibble: 3 x 4 # Groups: new [3] new x y z <int> <chr> <chr> <chr> 1 1 one two three 2 2 one four four (foo) 3 3 three three (foo) three (foo)
Upvotes: 1