Выполняйте и пишите функции для данных, используя `by` в data.table - PullRequest
0 голосов
/ 27 апреля 2020

Я использую data.table в R и пытаюсь создать и выполнить некоторые функции, которые будут выполнять некоторые вычисления для группы (DT[i, j, by = ....]), но мне нужно выполнять функции для всего набора данных в функции. В качестве примера, взяв данные радужной оболочки, я могу сделать следующее, чтобы получить разницу между групповыми и общими средними значениями («отклонения»):

library(data.table)
dtIris <- data.table(iris)

# Sample means by group
dtIris[, mean(Petal.Length), by = "Species"]

# Overall sample mean
dtIris[, mean(Petal.Length)]

# Group deviations 
dtIris[, mean(Petal.Length), by = "Species"][, V1] - dtIris[, mean(Petal.Length)]

В качестве альтернативы я могу сделать это немного более элегантным с помощью aggregate() чтобы получить это в одном выражении:

# Within a single expression 
dtIris[, aggregate(Petal.Length ~ Species, FUN = mean)[,2] - mean(Petal.Length)]

И вставить это в функцию

# Create function
dtDeviations <- function(x, by){
  aggregate(x ~ by, FUN = mean)[,2] - mean(x)
}
dtIris[, dtDeviations(Petal.Length, Species)]

Мой вопрос, есть ли способ сделать это "data.table -way "так, чтобы я мог заставить мою функцию взаимодействовать с аргументом by в нотации data.table и получить средства до и после группировки? Это означало бы, что я мог бы сделать вышеупомянутое, выполнив:

dtIris[, dtDeviations(Petal.Length), by = "Species"]

Одним из возможных решений было бы повторение среднего значения группы по длине каждой группы, причем среднее значение этого вектора является общим средним. Представляется разумным, что был бы способ получить доступ и сгруппировать значения внутри функции. Это было бы похоже на

# Reconstructed overall mean
dtIris[, rep(mean(Petal.Length), .N), by = "Species"][, mean(V1)]

Ответы [ 3 ]

1 голос
/ 27 апреля 2020

Еще один вариант получения одного выражения:

dtIris[, .SD[, mean(Petal.Length), by = Species]$V1 - mean(Petal.Length)]

Вывод:

[1] -2.296  0.502  1.794

Что касается функциональной формы, то в ее простейшей версии вы можете сделать:

dtDeviations <- function(dt, x, by){
  dt[, .SD[, mean(get(x)), by = get(by)]$V1 - mean(get(x))]
}

# Call it like below

dtDeviations(dtIris, 'Petal.Length', 'Species')
1 голос
/ 27 апреля 2020

Или просто

dtIris[, mean(Petal.Length)-mean(dtIris$Petal.Length), by = "Species"]

1 голос
/ 27 апреля 2020

Не уверен, что вы найдете это более элегантным, но это еще один вариант:

dtIris[, .(sum(Petal.Length), .N), by = "Species"
       ][, V1/N - sum(V1) / sum(N)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...