将常量列添加到嵌套的data.table

时间:2015-07-08 15:22:03

标签: r data.table

我正在使用jsonlite加载一些JSON数据,这导致一些嵌套数据(在结构中)与下面构造的玩具data.table dt类似。

设置:

dt <- data.table(a=c("abc", "def", "ghi"), b=runif(3))
dt[, c:=list(list(data.table(d=runif(4), e=runif(4))))]
dt
     a         b            c
1: abc 0.2623218 <data.table>
2: def 0.7092507 <data.table>
3: ghi 0.2795103 <data.table>

在我的数据中,存在键/标识符列(例如,上面a中的列data.table),但嵌套数据没有这样的标识符。我需要使用嵌套数据(请参阅我的related question),但在使用rbindlist之前,我想将列a的值作为嵌套数据的常量列。

例如,第一行中c的值为:

dt[1, c]
[[1]]
            d         e
1: 0.27951027 0.6350479
2: 0.45996594 0.6148956
3: 0.29377315 0.8432641
4: 0.01850265 0.1346082

我的目标是修改它,使它在将嵌套表绑定到一起之前看起来如下所示,以便我知道哪些行与哪条记录一起使用:

dt[1, c]
[[1]]
            d         e   a
1: 0.27951027 0.6350479 abc
2: 0.45996594 0.6148956 abc
3: 0.29377315 0.8432641 abc
4: 0.01850265 0.1346082 abc

我可以使用在J-expression中调用的自定义函数来实现这一点,并为该行以及常量列(此示例中为data.table)获取嵌套a名称和值。有点像:

add_nested_column <- function(dfl, name, value) {
  df <- dfl[[1]] # data.frame wrapped in list per row, pull it out
  df[, c(name):=value]  
  return(list(list(df)))
}

像这样使用:

dt[, key:=1:.N]
dt[, c:=add_nested_column(c, "a", a), by=key]
rbindlist(dt[, c])
             d         e   a
 1: 0.27951027 0.6350479 abc
 2: 0.45996594 0.6148956 abc
 3: 0.29377315 0.8432641 abc
 4: 0.01850265 0.1346082 abc
 5: 0.27951027 0.6350479 def
 6: 0.45996594 0.6148956 def
 7: 0.29377315 0.8432641 def
 8: 0.01850265 0.1346082 def
 9: 0.27951027 0.6350479 ghi
10: 0.45996594 0.6148956 ghi
11: 0.29377315 0.8432641 ghi
12: 0.01850265 0.1346082 ghi

这个解决方案对我来说似乎并不是那么糟糕,但我想知道它是否真的是最佳实践,或者是否有data.table内置的功能或我不知道的其他技术会使它成为现实更有效/简洁。

1 个答案:

答案 0 :(得分:3)

To achieve the end result, the most straightforward way is

dt[,c[[1]],by=a]

which gives

      a         d          e
 1: abc 0.9082078 0.66079779
 2: abc 0.2016819 0.62911404
 3: abc 0.8983897 0.06178627
 4: abc 0.9446753 0.20597457
 5: def 0.9082078 0.66079779
 6: def 0.2016819 0.62911404
 7: def 0.8983897 0.06178627
 8: def 0.9446753 0.20597457
 9: ghi 0.9082078 0.66079779
10: ghi 0.2016819 0.62911404
11: ghi 0.8983897 0.06178627
12: ghi 0.9446753 0.20597457

You can alternately do

rbindlist( setNames(dt[["c"]], dt[["a"]]), idcol = TRUE )

Data

set.seed(1)
dt <- data.table(a=c("abc", "def", "ghi"), b=runif(3))
dt[, c:=list(list(data.table(d=runif(4), e=runif(4))))]