【问题标题】:Perform and write functions on data using `by` in data.table使用 data.table 中的 `by` 对数据执行和编写函数
【发布时间】:2020-04-27 12:43:41
【问题描述】:

我在 R 中使用 data.table 并尝试创建和执行一些函数,这些函数将对每个组进行一些计算 (DT[i, j, by = ....]),但我需要在函数内对整个数据集执行函数。例如,以虹膜数据为例,我可以执行以下操作来获得组平均值和整体平均值之间的差异(“偏差”):

library(data.table)
dtIris <- data.table(iris)

# Sample means by group
dtIris[, mean(Petal.Length), by = "Species"]

# Overall sample mean
dtIris[, mean(Petal.Length)]

# Group deviations 
dtIris[, mean(Petal.Length), by = "Species"][, V1] - dtIris[, mean(Petal.Length)]

或者,我可以使用aggregate() 使其更优雅一点,以将其转化为一个表达式:

# Within a single expression 
dtIris[, aggregate(Petal.Length ~ Species, FUN = mean)[,2] - mean(Petal.Length)]

然后将其弹出到一个函数中

# Create function
dtDeviations <- function(x, by){
  aggregate(x ~ by, FUN = mean)[,2] - mean(x)
}
dtIris[, dtDeviations(Petal.Length, Species)]

我的问题是,有没有办法让它适合“data.table-way”,以便我可以让我的函数与 data.table 表示法中的by 参数交互并在之前获得手段并在分组之后?这意味着我可以通过执行来完成上述操作:

dtIris[, dtDeviations(Petal.Length), by = "Species"]

一种可能的解决方案是使组均值按每个组的长度重复,该向量的均值是整体均值。似乎有一种方法可以访问函数中的分组值并对其采取行动。这类似于

# Reconstructed overall mean
dtIris[, rep(mean(Petal.Length), .N), by = "Species"][, mean(V1)]

【问题讨论】:

  • 当您使用by 时,j 只会看到与by 对应的dtIris 的每个子集。您需要参考 dtIris 来查看整个 Petal.Length 向量
  • 是的,但原则上它还可以查看三个组的平均值和每个组的计数,从而可以重建整体平均值,例如:x1 &lt;- rnorm(112, 0, 1); x2 &lt;- rnorm(481, 1, 1); mean(c(x1,x2)); mean(c(rep(mean(x1), length(x1)), rep(mean(x2), length(x2))))
  • 在计算第一组的平均值时,尚未计算其他 2 组的平均值。这种构造的用例是什么?下面有很多很好的建议,可以在进入分组级别之前在全局级别进行计算
  • 我的问题中的示例也表明我可以首先在全局级别执行此操作,但我想知道是否可以(以及如何)按照标准 dt[i,j,by] 语法内联执行此操作...这就是问题所说的

标签: r data.table


【解决方案1】:

不确定您是否会觉得这更优雅,但这是另一种选择:

dtIris[, .(sum(Petal.Length), .N), by = "Species"
       ][, V1/N - sum(V1) / sum(N)]

【讨论】:

  • 感谢您的贡献-我认为您在获取组数和组均值以重建总体均值方面处于正确的位置-但我正在尝试找到一种方法来解决我的dt[i,j,by] 调用我的函数并在非分组级别上执行操作的信息
【解决方案2】:

或者只是

dtIris[, mean(Petal.Length)-mean(dtIris$Petal.Length), by = "Species"]

【讨论】:

  • 感谢您的输入,但我正试图找到一种方法(如果可能的话)来制作像偏差函数这样的函数,而只需指定一次变量(并且只指定变量)在 data.table 的 by 参数的函数中提供分组信息,而不仅仅是一种替代方法来做我已经得到的
【解决方案3】:

获取一个表达式的另一种选择是:

dtIris[, .SD[, mean(Petal.Length), by = Species]$V1 - mean(Petal.Length)]

输出:

[1] -2.296  0.502  1.794

至于函数形式,您可以使用其最简单的版本:

dtDeviations <- function(dt, x, by){
  dt[, .SD[, mean(get(x)), by = get(by)]$V1 - mean(get(x))]
}

# Call it like below

dtDeviations(dtIris, 'Petal.Length', 'Species')

【讨论】:

  • 感谢@arg0naut91,但我正在尝试让函数(和类似函数)在 data.table 样式中工作,因此需要了解如何利用来自 @987654324 的信息@ 在我的函数中
猜你喜欢
  • 2012-11-25
  • 2016-05-13
  • 2021-04-22
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
相关资源
最近更新 更多