Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R:组合两个函数以使用data.table聚合数据_R_Ggplot2_Aggregate_Data.table - Fatal编程技术网

R:组合两个函数以使用data.table聚合数据

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

下面是我正在处理的数据“类型/结构”,它包括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"), 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)