如何在函数中使用命名变量

时间:2018-06-28 22:23:22

标签: r for-loop data.table lapply

假定以下虚拟数据帧:

dt <- data.table(A=c("a", "a", "a", "b", "b", "b", "c", "c", "c", "d", "d", "d"), 
             B=c("e", "e", "e", "e", "e", "e", "f", "f", "f", "f", "f", "f"), 
             C=1:12, 
             D=13:24)

我想计算每个数字列(“ C”和“ D”)以及每次按因子列c(“ A”),c(”分组的时间的一些统计量(例如,均值和标准差) B“)和c(” A“,” B)。在实际的数据框中,我大约有40个数字列,10个因子列,它们以不同的组合进行分组,并且我想计算大量的统计信息。 基于我从上一个问题中得到的answer(通过@thelatemail),我知道我可以使用以下代码使用列表来处理因子分组(by =):

groupList <- list(c("A", "B"), c("A"), c("B"))
out <- vector("list", 3)
out <- lapply(
  groupList,
  function(x) {
    dt[, .(mean=mean(C), sd=sd(C)), by=x]
  }
)

现在,我想更进一步,创建一个包含数据框中数字列名称列表的变量,并在上面的函数中使用该变量的名称。我给出了以下代码,但不幸的是,它不起作用。我的想法是在每次旋转时使用循环从measureList提取值,并将该值放置在均值sd函数中。有任何想法吗?循环是我倾向于想到这些事情的方式,但是如果它使代码更快或更高效(特别是因为我拥有的一个因素列具有90个级别),我将很高兴摆脱它。我将不胜感激任何指针来解决这个问题!谢谢。

factorList <- list(c("A"), c("B"), c("A", "B"))
measureList <- list(c("C"), c("D"))

out <- vector("list", 2)
for(i in 1:length(measureList)){
  out[[i]] <-lapply(
    factorList,
    function(x) {
      dt[, .(mean=mean(eval(measureList[[i]])), 
             sd=sd(eval(measureList[[i]]))),
         by = x]
    }
  )
}

3 个答案:

答案 0 :(得分:2)

另一种可能性是使用中新的groupingsets函数:

groupingsets(dt
             , j = lapply(.SD, function(x) list(mean(x), sd(x)))
             , by = c('A','B')
             , sets = factorList)[, type := c('mean','sd')][]

给出:

      A    B        C        D type
 1:    a <NA>        2       14 mean
 2:    a <NA>        1        1   sd
 3:    b <NA>        5       17 mean
 4:    b <NA>        1        1   sd
 5:    c <NA>        8       20 mean
 6:    c <NA>        1        1   sd
 7:    d <NA>       11       23 mean
 8:    d <NA>        1        1   sd
 9: <NA>    e      3.5     15.5 mean
10: <NA>    e 1.870829 1.870829   sd
11: <NA>    f      9.5     21.5 mean
12: <NA>    f 1.870829 1.870829   sd
13:    a    e        2       14 mean
14:    a    e        1        1   sd
15:    b    e        5       17 mean
16:    b    e        1        1   sd
17:    c    f        8       20 mean
18:    c    f        1        1   sd
19:    d    f       11       23 mean
20:    d    f        1        1   sd

答案 1 :(得分:1)

这使用了dplyrpurrr,但我认为它是可行的。

library(dplyr)
library(purrr)

combos <- expand.grid(factorList, measureList)
map2(combos[, 1],
     combos[, 2],
     ~ dt %>% group_by_at(.x) %>% summarize_at(.y, funs(mean, sd)))

答案 2 :(得分:1)

您可以将outer与矢量化功能一起使用,也可以如下使用Map

m = function(x,y)dt[, .(mean=mean(get(y)), sd=sd(get(y))), by=x]

c(outer(factorList,measureList,Vectorize(m)))

Map(m,rep(factorList,each=length(measureList)),measureList)

编辑:

拥有名字:

m = function(x,y)setNames(dt[, .(mean(get(y)),sd(get(y))), by=x],
                          c(head(names(dt),length(x)),paste(c("mean","sd"),y,sep="_")))

c(outer(factorList,measureList,Vectorize(m)))