通过将行折叠为新的data.tables来创建嵌套的data.tables

dnl*_*rky 8 nested r data.table

如何创建包含嵌套data.tables的data.table?

set.seed(7908)
dt <- data.table(x=1:5)[,list(y=letters[1:x],z=sample(1:100,x)),by=x]

dt
##     x y  z
##  1: 1 a 13
##  2: 2 a 27
##  3: 2 b 87
##  4: 3 a 85
##  5: 3 b 98
##  6: 3 c  1
##  7: 4 a 53
##  8: 4 b 81
##  9: 4 c 64
## 10: 4 d 45
## 11: 5 a 28
## 12: 5 b 26
## 13: 5 c 52
## 14: 5 d 55
## 15: 5 e 12
Run Code Online (Sandbox Code Playgroud)

期望的输出

对于dt中x的每个唯一值,折叠行并创建一个data.table,其中列y和z包含在单个dt列中.结果应如下所示:

##    x        dt.yz
## 1: 1 <data.table>
## 2: 2 <data.table>
## 3: 3 <data.table>
## 4: 4 <data.table>
## 5: 5 <data.table>
Run Code Online (Sandbox Code Playgroud)

在我的实际例子中,我有几个具有不同列的数据表,我想将它存储在单个元数据表中.

dnl*_*rky 10

使用y和z作为列创建data.table,然后将其包装在列表中,以便可以将其"填充"在一行中.将其包装在另一个列表中,您可以在其中分配生成的列名称.使用by=x为x的每个唯一值做到这一点.

dt2 <- dt[, list(dt.yz=list(data.table(y, z))), by=x]
dt2
##    x        dt.yz
## 1: 1 <data.table>
## 2: 2 <data.table>
## 3: 3 <data.table>
## 4: 4 <data.table>
## 5: 5 <data.table>
Run Code Online (Sandbox Code Playgroud)

正如Arun指出的那样,使用.SD更短更快,可能更方便:

dt2 <- dt[, list(dt.yz=list(.SD)), by=x]
## dt.yz will include all columns not in the `by=`;
## Use `.SDcols=` to select specific columns
Run Code Online (Sandbox Code Playgroud)

要在以后获取data.table的值,请根据所需的x值对meta data.table(dt2)进行子集化,然后获取dt列表中的第一个元素(即嵌套的data.table). yz专栏.

dt2[x==5,dt.yz[[1]]]
##    y  z
## 1: a 28
## 2: b 26
## 3: c 52
## 4: d 55
## 5: e 12
Run Code Online (Sandbox Code Playgroud)

  • @Arun这太好了!这种模式是`tidyverse'中的**nest**和**unfst**的`data.table`版本(应该提升更多;已经找了很长时间)... @jangorecki反向操作是:`dt [,dt.yz [[1]],by = x]` (3认同)
  • 你可以改用`.SD`.`dt [,list(dt.yz = list(.SD)),by = x]` (2认同)