R - 如何根据多个因素和 return 原始列名 运行 不同 data.table 列的平均值和最大值
R - How to run average & max on different data.table columns based on multiple factors & return original colnames
我正在将我的 R 代码从 data.frame
+ plyr
更改为 data.table
s,因为我需要一种更快、更节省内存的方式来处理大数据集。不幸的是,我的 R 技能非常有限,我一整天都碰壁了。 SO高手不胜指教
我的目标
- 在我的 data.table 中基于 2 个函数聚合行 - 平均值和最大值 - 运行 在选定的列上(列名通过向量传递),同时按列分组也通过向量传递。
- 生成的 DT 应包含原始列名。
- 应该不要为了节省内存而不必要地复制设备标识符
我的测试代码
DT = data.table( a=LETTERS[c(1,1,1:4)],b=4:9, c=3:8, d = rnorm(6),
e=LETTERS[c(rep(25,3),rep(26,3))], key="a" )
GrpVar1 <- "a"
GrpVar2 <- "e"
VarToMax <- "b"
VarToAve <- c( "c", "d")
我试过但没有用的东西
DT[, list( b=max( b ), c=mean(c), d=mean(d) ), by=c( GrpVar1, GrpVar2 ) ]
# Hard-code col name - not what I want
DT[, list( max( get(VarToMax) ), mean( get(VarToAve) )), by=c( GrpVar1, GrpVar2 ) ]
# Col names become 'V1', 'V2', worse, 1 column goes missing - Not what I want either
DT[, list( get(VarToMax)=max( get(VarToMax) ),
get(VarToAve)=mean( get(VarToAve) ) ), by=c( GrpVar1, GrpVar2 ) ]
# Above code gave Error!
补充问题
基于我对 DT 的非常有限的理解,with = F
参数应该指示 R 解析 VarToMax 和 VarToAve 的值,但是 运行 宁下面的代码会导致错误。
DT[, list( max(VarToMax), mean(VarToAve) ), by=c( GrpVar1, GrpVar2 ), with=F ]
# Error in `[.data.table`(DT, , list(max(VarToMax), mean(VarToAve)), by = c(GrpVar1, :
# object 'ansvals' not found
# In addition: Warning message:
# In mean.default(VarToAve) :
# argument is not numeric or logical: returning NA
现有的SO解决方案无济于事
A运行的solution was how I got to this point, but I am very stuck. His other solution使用lapply
和.SDcols
涉及创建2个额外的DT,这不符合我的内存节省要求。
dt1 <- dt[, lapply(.SD, sum), by=ID, .SDcols=c(3,4)]
dt2 <- dt[, lapply(.SD, head, 1), by=ID, .SDcols=c(2)]
我对 data.table 很困惑!任何帮助将不胜感激!
这是我的拙劣尝试
DT[, as.list(c(setNames(max(get(VarToMax)), VarToMax),
lapply(.SD[, ..VarToAve], mean))),
c(GrpVar1, GrpVar2)]
# a e b c d
# 1: A Y 6 4 -0.8000173
# 2: B Z 7 6 0.2508633
# 3: C Z 8 7 1.1966517
# 4: D Z 9 8 1.7291615
或者,为了获得最大效率,您可以使用 colMeans
和 eval(as.name())
组合而不是 lapply
和 get
DT[, as.list(c(setNames(max(eval(as.name(VarToMax))), VarToMax),
colMeans(.SD[, ..VarToAve]))),
c(GrpVar1, GrpVar2)]
# a e b c d
# 1: A Y 6 4 -0.8000173
# 2: B Z 7 6 0.2508633
# 3: C Z 8 7 1.1966517
# 4: D Z 9 8 1.7291615
以与@David Arenburg 类似的方式,但使用 .SDcols
以简化符号。我还显示代码直到合并。
DTaves <- DT[, lapply(.SD, mean), .SDcols = VarToAve, by = c(GrpVar1, GrpVar2)]
DTmaxs <- DT[, lapply(.SD, max), .SDcols = VarToMax, by = c(GrpVar1, GrpVar2)]
merge(DTmaxs, DTaves)
## a e b c d
## 1: A Y 6 4 0.2230091
## 2: B Z 7 6 0.5909434
## 3: C Z 8 7 -0.4828223
## 4: D Z 9 8 -1.3591240
或者,您可以通过使用 ..
符号对 .SD
进行子集化来一次性完成此操作,以在 .SD
的父框架中查找 VarToAve
(如与名为 VarToAve
)
的列相对
DT[, c(lapply(.SD[, ..VarToAve], mean),
lapply(.SD[, ..VarToMax], max)),
by = c(GrpVar1, GrpVar2)]
## a e c d b
## 1: A Y 4 0.2230091 6
## 2: B Z 6 0.5909434 7
## 3: C Z 7 -0.4828223 8
## 4: D Z 8 -1.3591240 9
我正在将我的 R 代码从 data.frame
+ plyr
更改为 data.table
s,因为我需要一种更快、更节省内存的方式来处理大数据集。不幸的是,我的 R 技能非常有限,我一整天都碰壁了。 SO高手不胜指教
我的目标
- 在我的 data.table 中基于 2 个函数聚合行 - 平均值和最大值 - 运行 在选定的列上(列名通过向量传递),同时按列分组也通过向量传递。
- 生成的 DT 应包含原始列名。
- 应该不要为了节省内存而不必要地复制设备标识符
我的测试代码
DT = data.table( a=LETTERS[c(1,1,1:4)],b=4:9, c=3:8, d = rnorm(6),
e=LETTERS[c(rep(25,3),rep(26,3))], key="a" )
GrpVar1 <- "a"
GrpVar2 <- "e"
VarToMax <- "b"
VarToAve <- c( "c", "d")
我试过但没有用的东西
DT[, list( b=max( b ), c=mean(c), d=mean(d) ), by=c( GrpVar1, GrpVar2 ) ]
# Hard-code col name - not what I want
DT[, list( max( get(VarToMax) ), mean( get(VarToAve) )), by=c( GrpVar1, GrpVar2 ) ]
# Col names become 'V1', 'V2', worse, 1 column goes missing - Not what I want either
DT[, list( get(VarToMax)=max( get(VarToMax) ),
get(VarToAve)=mean( get(VarToAve) ) ), by=c( GrpVar1, GrpVar2 ) ]
# Above code gave Error!
补充问题
基于我对 DT 的非常有限的理解,with = F
参数应该指示 R 解析 VarToMax 和 VarToAve 的值,但是 运行 宁下面的代码会导致错误。
DT[, list( max(VarToMax), mean(VarToAve) ), by=c( GrpVar1, GrpVar2 ), with=F ]
# Error in `[.data.table`(DT, , list(max(VarToMax), mean(VarToAve)), by = c(GrpVar1, :
# object 'ansvals' not found
# In addition: Warning message:
# In mean.default(VarToAve) :
# argument is not numeric or logical: returning NA
现有的SO解决方案无济于事
A运行的solution was how I got to this point, but I am very stuck. His other solution使用lapply
和.SDcols
涉及创建2个额外的DT,这不符合我的内存节省要求。
dt1 <- dt[, lapply(.SD, sum), by=ID, .SDcols=c(3,4)]
dt2 <- dt[, lapply(.SD, head, 1), by=ID, .SDcols=c(2)]
我对 data.table 很困惑!任何帮助将不胜感激!
这是我的拙劣尝试
DT[, as.list(c(setNames(max(get(VarToMax)), VarToMax),
lapply(.SD[, ..VarToAve], mean))),
c(GrpVar1, GrpVar2)]
# a e b c d
# 1: A Y 6 4 -0.8000173
# 2: B Z 7 6 0.2508633
# 3: C Z 8 7 1.1966517
# 4: D Z 9 8 1.7291615
或者,为了获得最大效率,您可以使用 colMeans
和 eval(as.name())
组合而不是 lapply
和 get
DT[, as.list(c(setNames(max(eval(as.name(VarToMax))), VarToMax),
colMeans(.SD[, ..VarToAve]))),
c(GrpVar1, GrpVar2)]
# a e b c d
# 1: A Y 6 4 -0.8000173
# 2: B Z 7 6 0.2508633
# 3: C Z 8 7 1.1966517
# 4: D Z 9 8 1.7291615
以与@David Arenburg 类似的方式,但使用 .SDcols
以简化符号。我还显示代码直到合并。
DTaves <- DT[, lapply(.SD, mean), .SDcols = VarToAve, by = c(GrpVar1, GrpVar2)]
DTmaxs <- DT[, lapply(.SD, max), .SDcols = VarToMax, by = c(GrpVar1, GrpVar2)]
merge(DTmaxs, DTaves)
## a e b c d
## 1: A Y 6 4 0.2230091
## 2: B Z 7 6 0.5909434
## 3: C Z 8 7 -0.4828223
## 4: D Z 9 8 -1.3591240
或者,您可以通过使用 ..
符号对 .SD
进行子集化来一次性完成此操作,以在 .SD
的父框架中查找 VarToAve
(如与名为 VarToAve
)
DT[, c(lapply(.SD[, ..VarToAve], mean),
lapply(.SD[, ..VarToMax], max)),
by = c(GrpVar1, GrpVar2)]
## a e c d b
## 1: A Y 4 0.2230091 6
## 2: B Z 6 0.5909434 7
## 3: C Z 7 -0.4828223 8
## 4: D Z 8 -1.3591240 9