如何在data.table中"取消列出"列

Vas*_*y A 13 r data.table

在我的表中,一些单元格是向量而不是单个值,即列是列表而不是向量:

dt1 <- data.table(
  colA=   c('A1','A2','A3'), 
  colB=list('B1',c('B2a','B2b'),'B3'),
  colC=   c('C1','C2','C3'), 
  colD=   c('D1','D2','D3')
)

dt1
#   colA    colB colC colD
#1:   A1      B1   C1   D1
#2:   A2 B2a,B2b   C2   D2
#3:   A3      B3   C3   D3 
Run Code Online (Sandbox Code Playgroud)

我需要将其重新整理成一个长格式的列表colB.到目前为止我这样做:

dt1[,.(colB=unlist(colB)),by=.(colA,colC,colD)]
#   colA colC colD colB
#1:   A1   C1   D1   B1
#2:   A2   C2   D2  B2a
#3:   A2   C2   D2  B2b
#4:   A3   C3   D3   B3
Run Code Online (Sandbox Code Playgroud)

它完成了工作,但我不喜欢我必须明确指出所有其他列名称by=.有没有更好的方法来做到这一点?
(我确定它已经在其他地方得到了解答,但到目前为止我找不到它)

PS理想情况下我想管理没有任何外部包

Mic*_*ico 8

我认为@ Jaap是最简单的,但这是另一种咀嚼方式:

#create ID column
dt1[ , ID := .I]

#unnest colB, keep ID column
dt_unnest = dt1[ , .(ID = rep(ID, lengths(colB)),
                     colB = unlist(colB))]
#merge
dt_unnest = dt_unnest[dt1[ , !'colB'], on = 'ID']
#    ID colB colA colC colD
# 1:  1   B1   A1   C1   D1
# 2:  2  B2a   A2   C2   D2
# 3:  2  B2b   A2   C2   D2
# 4:  3   B3   A3   C3   D3
Run Code Online (Sandbox Code Playgroud)

  • 或者,`dt1 [rep(1:.N,lengths(colB))] [,colB:= unlist(dt1 $ colB)] []`.我更喜欢这种超级组合的东西(出现在Jaap和你的中),因为我希望能减慢速度. (6认同)

Jaa*_*aap 8

将我的评论推荐给答案.使用:

dt1[,.(colB = unlist(colB)), by = setdiff(names(dt1), 'colB')]
Run Code Online (Sandbox Code Playgroud)

得到:

   colA colC colD colB
1:   A1   C1   D1   B1
2:   A2   C2   D2  B2a
3:   A2   C2   D2  B2b
4:   A3   C3   D3   B3
Run Code Online (Sandbox Code Playgroud)

或者作为替代方案(@ Frank提议的略微变化):

dt1[rep(dt1[,.I], lengths(colB))][, colB := unlist(dt1$colB)][]
Run Code Online (Sandbox Code Playgroud)