r - R:data.table,按存储在变量中的列名聚合数据框
问题描述
假设我有一个像这样的数据框iris
:
> data(iris)
> head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
Sepal.Width
例如,我想聚合数据框,以便获得each的平均值Species
。在那种情况下,我会这样做:
> library(data.table)
> dd <- data.table(iris)
> dagg <- as.data.frame(dd[, list(Mean.value=mean(Sepal.Width)), by=list(ID=Species)])
> dagg
ID Mean.value
1 setosa 3.428
2 versicolor 2.770
3 virginica 2.974
但是,我现在面临的情况是它是函数的一部分,我为不同的数据框和不同的列执行此操作。
所以现在我将列名存储在变量中,所以我尝试:
> idvar <- "Species"
> valvar <- "Sepal.Width"
> dd <- data.table(iris)
> dagg <- as.data.frame(dd[, list(Mean.value=mean(iris[,valvar])), by=list(ID=iris[,idvar])])
> dagg
ID Mean.value
1 setosa 3.057333
2 versicolor 3.057333
3 virginica 3.057333
结果显然是错误的;正确执行此操作的方法是什么?谢谢!
解决方案
您可以换行.SDcols
并by
在其中c()
将列作为字符串传递。
library(data.table)
dd <- data.table(iris)
aggregator <- function(DT, col2avg, new.name = "avg", by = NULL) {
out <-
if (is.null(by)) {
DT[, lapply(.SD, mean), .SDcols = c(col2avg)][]
} else {
DT[, lapply(.SD, mean), .SDcols = c(col2avg), by = c(by)][]
}
setnames(out, col2avg, new.name)
out[]
}
aggregator(dd, col2avg = "Sepal.Width", by = "Species", new.name = "Mean.value")
#> Species Mean.value
#> 1: setosa 3.428
#> 2: versicolor 2.770
#> 3: virginica 2.974
setnames(out, by, "ID")
(如果你需要,再加上一个额外的)。
使用by = c(by)
而不是by = by
明确表示 RHS 是一个表示列名的字符串,因为data.table
将首先查找一个名为"by"
而不管by
表外的 ' 值的列。
推荐阅读
- php - PHP 表单 $POST 未完整发送
- node.js - Windows 10 上的 NodeJS 和 Linux 的 Windows 子系统
- python - 如何将多个一维列表连接成一个二维列表?
- vba - Outlook VBA VLOOKUP 转换为 Excel 文件
- bash - 用 DNA 字母替换数字基因型代码
- laravel - Laravel VUEJS如何传递v-model的值
- configuration - 使用 L2TP/IPSEC 凭据创建 OpenVPN 文件
- html - 从宽度中删除水平滚动
- sql - 通过连接两个表来获取不同的列
- swift - 为什么 Combine 的 receive(on:) 操作符会吞下错误?