Передача нескольких имен столбцов в «by» в функции data.table - PullRequest
2 голосов
/ 29 января 2020

Я прочитал много постов о передаче имен столбцов в функцию data.table, но я не видел пост, посвященный передаче нескольких переменных в «by». Я обычно использую такой код для вычисления сводной статистики по группам.

# Data
library(data.table)
dt=mtcars
setDT(dt)

# Summary Stats Example
dt[cyl==4,.(Count=.N,
    Mean=mean(hp),
    Median=median(hp)),
    by=.(am,vs)]

#    am vs Count   Mean Median
# 1:  1  1     7 80.571     66
# 2:  0  1     3 84.667     95
# 3:  1  0     1 91.000     91

Я не могу заставить работать следующую функцию:

# Function
myFun <- function(df,i,j,by){
    df[i==4,.(Count=.N,
      Mean=mean(j),
      Median=median(j)),
      by=.(am,by)]
}
myFun(dt,i='cyl',j='hp',by='vs')

Обратите внимание, что я жестко запрограммирован "4 "и" я "в функцию для этого примера. get() работал, когда использовался только 1 для группировки переменных, но не работал, когда использовалось несколько группирующих переменных. Руководство по правильному использованию get / quote / eval / replace / parse / as.name / et c при написании функций data.table приветствуется.

Ответы [ 2 ]

0 голосов
/ 31 января 2020

Я принял ответ sm95. Ниже приведен более сложный пример / решение, которое отправляет список с аргументом by:

# Libraries
library(data.table)

# Data
dt = mtcars
setDT(dt)

# Function to calculate summary statistics
myFun <- function(df, i1var, i1val, i2var, i2val,            # i arguments
                                    j,                       # j arguments
                                    by1var, by2var, by2val){ # by arguments
    df[get(i1var) == i1val & get(i2var) %in% i2val,
         .(Count = .N,
            Mean = mean(get(j)),
            Median = median(get(j))),
        by = .(get(by1var), get(by2var) == by2val)]
} # END Function

# Run function
myFun(dt,i1var = 'cyl', i1val = 4, i2var = 'gear', i2val = c(3,4),
            j = 'hp',
            by1var = 'vs', by2var = 'am', by2val = 1)
#    vs am Count     Mean Median
# 1:  1  1     6 75.16667     66
# 2:  1  0     3 84.66667     95

# Should match
dt[cyl == 4 & gear %in% c(3,4),
     .(Count = .N,
        Mean = mean(hp),
        Median = median(hp)),
     by = .(vs, am == 1)]
#    vs am Count     Mean Median
# 1:  1  1     6 75.16667     66
# 2:  1  0     3 84.66667     95

Вот моя шпаргалка:

  • Pass i, j и by переменные, использующие get(var)
  • Pass i или by критерии непосредственно

Вышеуказанное может не относиться к более сложным функциям и не может быть оптимальное.

Если by является вектором, а НЕ списком (например, by=c() против by=.()), то by аргументы могут быть переданы напрямую.

0 голосов
/ 29 января 2020

Просто создайте вектор символов для by части data.table, это будет работать:

myFun <- function(df, i, j, by){

 df[get(i) == 4, .(Count = .N, 
           Mean = mean(get(j)),
           Median = median(get(j))),
  by = c(by, 'am')]
}



myFun(dt, i = 'cyl', j = 'hp', by = 'vs')

#vs am Count     Mean Median
#1:  1  1     7 80.57143     66
#2:  1  0     3 84.66667     95
#3:  0  1     1 91.00000     91
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...