按组移动data.table中的一列列表

Chr*_*ris 2 r data.table

我在 R 中有一列列表:

DT <- data.table(foo = c(list(c("a","b","c")), list(c("b","c")), list(c("a","b")), list(c("a"))), id = c(1,1,2,2))
DT
     foo id
1: a,b,c  1
2:   b,c  1
3:   a,b  2
4:     a  2
Run Code Online (Sandbox Code Playgroud)

我想做的是复制典型的换班行为以获得:

     foo id
1:   b,c  1
2:    NA  1
3:     a  2
4:    NA  2
Run Code Online (Sandbox Code Playgroud)

对于普通列,我将使用 shift,但这会将列表拆分为列并移动这些列(并标记警告):

DT[ , shift(foo,1,type = "lead"), by = id]
   id V1 V2
1:  1  b  c
2:  1  c NA
3:  1 NA  c
4:  2  b NA
5:  2 NA NA
Run Code Online (Sandbox Code Playgroud)

如果我将 shift 调用包装到一个列表中,返回的是一个列表,但只有向量元素已被移动:

DT[ , list(shift(foo,1,type = "lead")), by = id]
   id     V1
1:  1 b,c,NA
2:  1   c,NA
3:  2   b,NA
4:  2     NA
Run Code Online (Sandbox Code Playgroud)

Aru*_*run 5

这已经不止一次出现了。所以我继续添加了这个功能。不过,您目前必须使用开发版本 v1.9.7 .. 请参阅此处的安装说明。

DT[, foo2 := shift(.(foo), type = "lead"), 
       by = id]
#      foo id foo2
# 1: a,b,c  1  b,c
# 2:   b,c  1   NA
# 3:   a,b  2    a
# 4:     a  2   NA
Run Code Online (Sandbox Code Playgroud)

只需将foo每个组包装在一个列表中。请注意,它返回一个列表列表:=如上所示,它可以很好地工作。如果您没有添加/更新 data.table(这没有多大意义),那么您必须提取列表元素。

DT[, .(foo2 = shift(.(foo), type="lead")[[1L]]), 
        by = id]
#    id foo2
# 1:  1  b,c
# 2:  1   NA
# 3:  2    a
# 4:  2   NA
Run Code Online (Sandbox Code Playgroud)

shift()旨在很好地使用 data.table 的:=语法,因为它始终返回相同数量的行。