Shifting the values of specific columns to the right in R

35 views Asked by At

I want to shift the values of specific columns to the right and keep the NAs on the left.

df = data.frame(a = c("one", "two", "three", "four", "five"), 
                x = c("l", "m", NA, NA, "p"),
                y = c(NA, "b", "c", NA, NA),
                z = c("u", NA, "w", "x", "y"))

      a    x    y    z
1   one    l <NA>    u
2   two    m    b <NA>
3 three <NA>    c    w
4  four <NA> <NA>    x
5  five    p <NA>    y

This is the output I want

   a      x     y     z
1  one   <NA>   l    u
2  two   <NA>   m    b 
3  three <NA>   c    w
4  four  <NA> <NA>   x
5  five  <NA>   p    y
2

There are 2 answers

0
benson23 On BEST ANSWER

You can do a row-wise apply on your df excluding the first column, combining NA with non-NA entries (by na.omit).

df[, -1] <- t(apply(df[, -1], 1, \(x) c(rep(NA, sum(is.na(x))), na.omit(x))))

     a    x    y z
1   one <NA>    l u
2   two <NA>    m b
3 three <NA>    c w
4  four <NA> <NA> x
5  five <NA>    p y
0
jay.sf On

You could remove NAs, rev and adjust lengths, and rev back .

> cls <- c('x', 'y', 'z')
> df[cls] <- df[cls] |> asplit(1) |> 
+   sapply(\(x) rev(`length<-`(rev(x[!is.na(x)]), length(cls)))) |> t()
> df
      a    x    y z
1   one <NA>    l u
2   two <NA>    m b
3 three <NA>    c w
4  four <NA> <NA> x

Data:

> dput(df)
structure(list(a = c("one", "two", "three", "four", "five"), 
    x = c(NA_character_, NA_character_, NA_character_, NA_character_, 
    NA_character_), y = c("l", "m", "c", NA, "p"), z = c("u", 
    "b", "w", "x", "y")), row.names = c(NA, -5L), class = "data.frame")