简体   繁体   中英

How shift values in rows in R (dplyr or data.table)?

Here is data set 'before' and 'after' shifting.

# Data set 'before'
df_before <- t(data.table(
  x = c(1, 2, 3, 4, 5),
  y = c(0, 6, 7, 8, 9),
  z = c(0, 0, 11, 12, 13)))

# Shift operation
# ...

# Data set 'after'
df_after <- t(data.table(
  x = c(1, 2, 3, 4, 5),
  y = c(6, 7, 8, 9, NA),
  z = c(11, 12, 13, NA, NA)))

How to make this kind of shifting on +1 cell only for all rows?

Thanks!

Something like this? Just start the rows always shifted by one and reset their length . The latter adds NA s.

t(sapply(1:nrow(DF), function(x) `length<-`(DF[x, x:ncol(DF)], ncol(DF))))
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    2    3    4    5
# [2,]    6    7    8    9   NA
# [3,]   11   12   13   NA   NA

Data

DF <- structure(c(1, 0, 0, 2, 6, 0, 3, 7, 11, 4, 8, 12, 5, 9, 13), .Dim = c(3L, 
5L), .Dimnames = list(c("x", "y", "z"), NULL))

Taking a guess at the logic:

t(apply(df_before, 1, function(x) `length<-`(x[x != 0], ncol(df_before))))

  [,1] [,2] [,3] [,4] [,5]
x    1    2    3    4    5
y    6    7    8    9   NA
z   11   12   13   NA   NA

You can un-transpose the df_before data.frame then use the lead function from dplyr to shift the columns

library(data.table)
library(dplyr)
df_before <- data.table(
  x = c(1, 2, 3, 4, 5),
  y = c(0, 6, 7, 8, 9),
  z = c(0, 0, 11, 12, 13))

df_after <- t(data.table(
  x = c(1, 2, 3, 4, 5),
  y = c(6, 7, 8, 9, NA),
  z = c(11, 12, 13, NA, NA)))

df_before[] <-lapply(1:ncol(df_before), function(x){
  dplyr::lead(df_before[[x]],n= x-1)
})

If you need to transpose the data after this step:

df_after2 <- t(df_before)

all.equal(df_after,df_after2) # TRUE

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM