【问题标题】:retaining column names in lapply(.SD,...) for data.table R在 lapply(.SD,...) 中为 data.table R 保留列名
【发布时间】:2015-04-27 21:56:47
【问题描述】:

将具有多个输出变量(例如列表)的函数应用于 data.table 的子集时,我会丢失变量名称。有没有办法留住他们?

library(data.table)

foo <- function(x){
  list(mn = mean(x), sd = sd(x))
}

bar <- data.table(x=1:8, y=c("d","e","f","g"))

# column names "mn" and "sd" are replaced by "V1" and "V2"
bar[, sapply(.SD, foo), by = y, .SDcols="x"]

# column names "mn" and "sd" are retained
bar_split <- split(bar$x, bar$y)
t(sapply(bar_split, foo))

【问题讨论】:

  • bar[,c("mn","sd"):=sapply(.SD,foo),.(y),.SDcols="x"]怎么样
  • 好问题。我有兴趣为返回不仅仅是标量列表的函数执行此操作,例如foo2 &lt;- function(x) list(mn=mean(x),tab=table(x))。

标签: r data.table


【解决方案1】:

我会用下面的,这有点尴尬,但是不管有多少函数都不需要手动写名字

bar[, as.list(unlist(lapply(.SD, foo))), by = y, .SDcols = "x"]
#    y x.mn     x.sd
# 1: d    3 2.828427
# 2: e    4 2.828427
# 3: f    5 2.828427
# 4: g    6 2.828427

这种方法的最大优点是它将函数与列名绑定在一起。例如,如果你有一个额外的列,它仍然会在使用与上面相同的代码时给出一个信息性的结果

set.seed(1)
bar[, z := sample(8)]
bar[, as.list(unlist(lapply(.SD, foo))), by = y, .SDcols = c("x", "z")]
#    y x.mn     x.sd z.mn      z.sd
# 1: d    3 2.828427  2.0 1.4142136
# 2: e    4 2.828427  7.5 0.7071068
# 3: f    5 2.828427  3.0 1.4142136
# 4: g    6 2.828427  5.5 0.7071068

【讨论】:

  • x 是否需要引用为"x"? - 至少在 1.9.4 中是这样。
  • @thelatemail 好点,我正在使用1.9.5。固定的。顺便说一句,在1.9.5 中,您现在可以执行诸如.SDcols = x:y 之类的操作。
  • 这适用于大多数简单的情况,但是否可以在不创建 n 新列的情况下使用 replicate 而不是 lapply 或 sapply?例如,bar[, replicate(n=3, foo(.SD$x)), .(y)] 为每个复制添加一对新的列,as.list(unlist(...)) 技巧似乎没有保留列名。
【解决方案2】:

setNames 函数可让您重新添加缺少的字符向量。:

bar[, setNames( sapply(.SD, foo), c("mn", "sd")), by = y, .SDcols="x"]
   y mn       sd
1: d  3 2.828427
2: e  4 2.828427
3: f  5 2.828427
4: g  6 2.828427

作者建议使用 Arenburg 建议的另一种形式:

DT[, c('x2', 'y2') := list(x / sum(x), y / sum(y)), by = grp]

【讨论】:

    猜你喜欢
    • 2015-11-23
    • 2015-09-12
    • 2016-11-12
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 2020-11-09
    相关资源
    最近更新 更多