Как использовать именованную переменную в функции - PullRequest
0 голосов
/ 29 июня 2018

Предположим следующий фиктивный фрейм данных:

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 столбцов факторов, которые группируются в различные комбинации, и большой список статистики, который я хотел бы рассчитать. Основываясь на ответе (от @thelatemail), который я получил из предыдущего вопроса, я знаю, что могу использовать приведенный ниже код для работы с группировками факторов (по =), используя список:

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 голосов
/ 29 июня 2018

Вы можете использовать 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)

EDIT:

ИМЕТЬ ИМЕНИ:

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)))
0 голосов
/ 29 июня 2018

Другая возможность - использовать новую функцию 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
0 голосов
/ 29 июня 2018

Используются dplyr и purrr, но я думаю, что это работает.

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)))
...