【问题标题】:R - pass fixed columns to lapply function in data.tableR - 将固定列传递给 data.table 中的 lapply 函数
【发布时间】:2013-11-26 23:33:55
【问题描述】:

我有一个 data.table,其中包含 p1p2、... 列,其中包含百分比。给定参考变量val,我想计算每列的分位数。从概念上讲,这就像:

quantile(val, p1, type = 4, na.rm = T)
quantile(val, p2, type = 4, na.rm = T)
...

我使用data.table的尝试如下:

fun <- function(x, y) quantile(y, x, type = 4, na.rm = T)
dt[, c('q1', 'q2') := lapply(.SD, fun), .SDcols = c('p1', 'p2'), by = grp]
where grp is some grouping variable

但是,我无法以固定不变的方式指定 y 变量。

我尝试了以下方法:

fun <- function(x, y, dt) quantile(dt[, y], x, type = 4, na.rm = T)
dt[, c('q1', 'q2') := lapply(.SD, fun, y, dt), .SDcols = c('p1', 'p2'), by = grp]

但是,在计算分位数时,这样做并不会强制进行分组。它将根据y 变量的整个范围而不是组内的y 计算分位数。这样做的正确方法是什么?

编辑:

这里是一个只有一个变量的简单示例:

> dt <- data.table(y = 1:10, p1 = rep(seq(0.2, 1, 0.2), 2), g = c(rep('a', 5), rep('b', 5)))
> dt
     y  p1 g
 1:  1 0.2 a
 2:  2 0.4 a
 3:  3 0.6 a
 4:  4 0.8 a
 5:  5 1.0 a
 6:  6 0.2 b
 7:  7 0.4 b
 8:  8 0.6 b
 9:  9 0.8 b
10: 10 1.0 b
> fun <- function(x, dt, y) quantile(dt[, y], x, type = 4, na.rm = T)
> dt[, c('q1') := lapply(.SD, fun, dt, y), .SDcols = c('p1'), by = c('g')]
> dt
     y  p1 g q1
 1:  1 0.2 a  2
 2:  2 0.4 a  4
 3:  3 0.6 a  6
 4:  4 0.8 a  8
 5:  5 1.0 a 10
 6:  6 0.2 b  2
 7:  7 0.4 b  4
 8:  8 0.6 b  6
 9:  9 0.8 b  8
10: 10 1.0 b 10

您可以看到 q1 是使用 y 的整个范围计算得出的。

【问题讨论】:

  • 您能否发布一个可重现的示例,包括 dt 包含的内容。变量y 是否真的与您希望计算分位数的百分比在同一个表中?
  • lapply 应该与一个参数的函数一起使用。如果您需要两个或更多,mapply 可能会有所帮助。
  • @mnel:我加了一个简单的例子
  • @Frank:您能否提供一个示例,说明如何在data.table 的上下文中使用mapply?特别是,如果我指定一个带有两个参数的函数,我如何告诉data.table 循环其中一个参数,同时保持另一个参数不变?
  • 我认为标准的 R 回收工作。也就是说,您可以传递一个长度为一个的列表和另一个长度为 n 的列表。

标签: r data.table


【解决方案1】:

我发现您将所需的百分比存储在与您希望用来计算分位数的数据相同的 data.table 中的想法非常奇怪,但是这是一种可行的方法

dt <- data.table(x=10:1,y = 1:10, p1 = rep(seq(0.2, 1, 0.2), 2), g = c(rep('a', 5), rep('b', 5)))


dt[, c('qx','qy') := Map(f = quantile, x = list(x, y), prob = list(p1), type = 4), by = g]

您可以在.SD 中使用.SDcols 来选择您想要的列

dt[, c('qx','qy') := Map(f = quantile, x = .SD[, .SDcols = c('x','y')], 
                         prob = list(p1), type = 4), by = g]

或使用with =FALSE

dt[, c('qx','qy') := Map(f = quantile, x = .SD[, c('x', 'y')], 
                          prob = list(p1), type = 4), by = g]

【讨论】:

  • 谢谢。它工作得很好。您是否知道如何通过字符串指定x?我有很多专栏vars &lt;- c('x1', 'x2', ...., 'x50'),我想以某种方式将其放入x = list(vars),但它没有用。
  • 我注意到与在.SD 中使用.SDcols 相比,使用with = FALSE 的速度大约是两倍。在.SD 上使用lapply 时,推荐使用.SDcols 方法,但在.SD 内使用.SDcol 时,这个结论似乎并不成立。你知道为什么或在某处记录了吗?
  • 因为在内部.SD中使用.SDcols会创建两次.SD ,而创建.SD很慢。
  • 谢谢。这很微妙(至少对我来说)。
猜你喜欢
  • 2019-02-01
  • 2020-12-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多