R:组合两个函数以使用data.table聚合数据
下面是我正在处理的数据“类型/结构”,它包括3个因子变量R:组合两个函数以使用data.table聚合数据,r,ggplot2,aggregate,data.table,R,Ggplot2,Aggregate,Data.table,下面是我正在处理的数据“类型/结构”,它包括3个因子变量 library(data.table) library(ggplot2) DT <- data.table(mtcars) DT[["cyl"]] <- factor(DT[["cyl"]]) DT[["gear"]] <- factor(DT[["gear"]]) DT[["vs"]] <- factor(DT[["vs"]]) DT <- DT[, c("cyl", "gear", "vs"), wit
library(data.table)
library(ggplot2)
DT <- data.table(mtcars)
DT[["cyl"]] <- factor(DT[["cyl"]])
DT[["gear"]] <- factor(DT[["gear"]])
DT[["vs"]] <- factor(DT[["vs"]])
DT <- DT[, c("cyl", "gear", "vs"), with=F]
setkey(DT, cyl, gear, vs)
这将是预期的产出:
DT_agg <- DT[, grp(cyl), by=vs]
在研究答案后编辑
使用agstudy版本的agg()
not_ok = agg(DT, cyl, vs)
print(not_ok)
# groupby1 x percentage label
# 1: 1 4 0.34375 34%
# 2: 1 6 0.21875 22%
# 3: 1 8 0.43750 44%
# 4: 0 4 0.34375 34%
# 5: 0 6 0.21875 22%
# 6: 0 8 0.43750 44%
我想知道函数如何在自身(第一种情况)而不是agg函数内部正确工作。好问题!特别是对于一些没有太多编程经验的人
使用eval
并简化您的函数(无需分配数据表):
我相信这是与1.8.11版本。也许在开发版本中发生了一些变化
library(data.table)
library(ggplot2)
DT <- data.table(mtcars)
DT[["cyl"]] <- factor(DT[["cyl"]])
DT[["gear"]] <- factor(DT[["gear"]])
DT[["vs"]] <- factor(DT[["vs"]])
DT <- DT[, c("cyl", "gear", "vs"), with=F]
setkey(DT, cyl, gear, vs)
grp <- function(x) {
percentage = as.numeric(table(x)/length(x))
list(x = levels(x),
percentage = percentage,
label = paste( round( as.numeric(table(x)/length(x), 0 ) * 100 ), "%")
)
}
agg <- function(data, x, groupby1, groupby2 = NULL,...){
data = substitute(data)
x = substitute(x)
groupby1 = substitute(groupby1)
groupby2 = substitute(groupby2)
if(is.null(groupby2)) eval(data)[, grp(eval(x)), by=groupby1]
else eval(data)[, grp(eval(x)),
by=list(eval((groupby1)),eval(groupby2))]
}
ok = DT[, grp(cyl), by = vs]
print(ok)
ok2 = agg(DT, cyl, vs)
print(ok2)
库(data.table)
图书馆(GG2)
太好了!谢谢你的回答@agstudy!这确实有助于理解这个概念。但是我得到了一个错误:eval(expr,envir,enclose)中的错误:找不到对象'cyl',调用自:(function(){.rs.breakError(TRUE)})(
以前的版本是这样调用它的,agg(DT,DT$cyl,vs)
但这将是第二个选项的理想选择。@MartínBel我只是在新的会话中再次测试它,它对我来说很好。如果仍然出现错误,请暂时取消选中答案,等待data.table specialist做出更好的尝试。我已用您的答案编辑了我的问题。由于某些原因,它对我不起作用。我已经安装了开发版本,并且该函数完全按照您编写的那样工作@马丁贝尔,我忘了!我有1.8.11版本
我使用DT[,grp(cyl),by=vs]
或agg(DT,cyl,vs)
获得了“不正常”版本,我用一个新的R会话再次尝试,得到了与编辑显示相同的输出。我不明白这怎么可能。也许它与数据表
版本有关?我用的是cran版本,1.8.10,我用的是1.8.11。奇怪。我会在回答中写下我在编辑中使用的代码。我尝试了1.8.1.1,得到了相同的结果。@mnel编辑版本与agstudy的答案有一些不同。安装了data.table的dev版本后,agstudy的原始答案非常有效。我会从两个方面得到好的版本。我已经用完整的工作代码写了另一个“答案”,这样更容易找到。
agg <- function(data, x, groupby1, groupby2 = NULL,...){
data = eval(substitute(data))
x = substitute(data$x) # changed this bit (it was producing an error)
groupby1 = substitute(groupby1)
groupby2 = substitute(groupby2)
if(is.null(eval(substitute(groupby2)))) {
eval(data)[, grp(eval(x)), by=groupby1]
} else {
eval(data)[, grp(eval(x)), by=list(eval((groupby1)),eval(groupby2))]
}
}
ok = DT[, grp(cyl), by = vs]
print(ok)
# vs x percentage label
# 1: 1 4 0.71428571 71%
# 2: 1 6 0.28571429 29%
# 3: 1 8 0.00000000 0%
# 4: 0 4 0.05555556 6%
# 5: 0 6 0.16666667 17%
# 6: 0 8 0.77777778 78%
not_ok = agg(DT, cyl, vs)
print(not_ok)
# groupby1 x percentage label
# 1: 1 4 0.34375 34%
# 2: 1 6 0.21875 22%
# 3: 1 8 0.43750 44%
# 4: 0 4 0.34375 34%
# 5: 0 6 0.21875 22%
# 6: 0 8 0.43750 44%
agg <- function(data, x, groupby1, groupby2 = NULL,...){
data = substitute(data)
x = substitute(x)
groupby1 = substitute(groupby1)
groupby2 = substitute(groupby2)
if(is.null(groupby2)) eval(data)[, grp(eval(x)), by=groupby1]
else eval(data)[, grp(eval(x)),
by=list(eval((groupby1)),eval(groupby2))]
}
agg(data = DT, x = cyl, groupby1 = vs,groupby2 = gear )
## groupby1 groupby2 x percentage label
## 1: 1 3 4 0.3333 33 %
## 2: 1 3 6 0.6667 67 %
## 3: 1 3 8 0.0000 0 %
## 4: 1 4 4 0.8000 80 %
## 5: 1 4 6 0.2000 20 %
## 6: 1 4 8 0.0000 0 %
## 7: 0 5 4 0.2500 25 %
## 8: 0 5 6 0.2500 25 %
## 9: 0 5 8 0.5000 50 %
## 10: 1 5 4 1.0000 100 %
## 11: 1 5 6 0.0000 0 %
## 12: 1 5 8 0.0000 0 %
## 13: 0 4 4 0.0000 0 %
## 14: 0 4 6 1.0000 100 %
## 15: 0 4 8 0.0000 0 %
## 16: 0 3 4 0.0000 0 %
## 17: 0 3 6 0.0000 0 %
## 18: 0 3 8 1.0000 100 %
library(data.table)
library(ggplot2)
DT <- data.table(mtcars)
DT[["cyl"]] <- factor(DT[["cyl"]])
DT[["gear"]] <- factor(DT[["gear"]])
DT[["vs"]] <- factor(DT[["vs"]])
DT <- DT[, c("cyl", "gear", "vs"), with=F]
setkey(DT, cyl, gear, vs)
grp <- function(x) {
percentage = as.numeric(table(x)/length(x))
list(x = levels(x),
percentage = percentage,
label = paste( round( as.numeric(table(x)/length(x), 0 ) * 100 ), "%")
)
}
agg <- function(data, x, groupby1, groupby2 = NULL,...){
data = substitute(data)
x = substitute(x)
groupby1 = substitute(groupby1)
groupby2 = substitute(groupby2)
if(is.null(groupby2)) eval(data)[, grp(eval(x)), by=groupby1]
else eval(data)[, grp(eval(x)),
by=list(eval((groupby1)),eval(groupby2))]
}
ok = DT[, grp(cyl), by = vs]
print(ok)
ok2 = agg(DT, cyl, vs)
print(ok2)