.EACHI в data.table

Я не могу найти документацию о том, что именно .EACHI делает в data.table. Я вижу короткое упоминание об этом в документации:

Агрегация для подмножества известных групп особенно эффективна при прохождении этих групп в я и установке by=.EACHI. Когда i является data.table, DT[i,j,by=.EACHI] оценивает j для групп DT, что каждая строка в i объединяется. Мы называем эту группировку каждым i.

Но что означают "группы" в контексте DT? Определяется ли группа ключом, установленным на DT? Является ли группа каждой отдельной строкой, которая использует все столбцы в качестве ключа? Я полностью понимаю, как запускать что-то вроде DT[i,j,by=my_grouping_variable], но я смущен тем, как будет работать .EACHI. Может кто-нибудь объяснить пожалуйста?

Ответ 1

Я добавил это в список здесь. И, надеюсь, мы сможем доставить, как и планировалось.


Вероятно, причина в том, что by=.EACHI - это недавняя функция (начиная с версии 1.9.4), но то, что она делает, не является. Позвольте мне объяснить пример. Предположим, что у нас есть два data.tables X и Y:

X = data.table(x = c(1,1,1,2,2,5,6), y = 1:7, key = "x")
Y = data.table(x = c(2,6), z = letters[2:1], key = "x")

Мы знаем, что можем присоединиться, выполнив X[Y]. это похоже на операцию подмножества, но с использованием data.tables (вместо целых чисел/имен строк или логических значений). Для каждой строки в Y, взяв столбцы ключей Y, она находит и возвращает соответствующие совпадающие строки в столбцах X (+ столбцы в Y).

X[Y]
#    x y z
# 1: 2 4 b
# 2: 2 5 b
# 3: 6 7 a

Теперь позвольте сказать, что для каждой строки из Y ключевых столбцов (здесь только один ключевой столбец) мы хотели бы получить количество совпадений в X. В версиях data.table < 1.9.4, мы можем сделать это, просто указав .N в j следующим образом:

# < 1.9.4
X[Y, .N]
#    x N
# 1: 2 2
# 2: 6 1

То, что это неявно делает, в присутствии j, оценивает j-expression для каждого согласованного результата X (соответствует строке в Y). Это вызвано by-without-by или implicit-by, потому что оно как бы скрыто.

Проблема заключалась в том, что это всегда будет выполнять операцию by. Итак, если бы мы хотели узнать количество строк после объединения, нам нужно было бы сделать: X[Y][ .N] (или просто nrow(X[Y]) в этом случае). То есть, мы не можем иметь выражение j в том же вызове, если мы не хотим by-without-by. В результате, когда мы сделали, например, X[Y, list(z)], он оценил list(z) с помощью by-without-by и был поэтому немного медленнее.

Кроме того, пользователи data.table запросили это как явное - см. this и this для большего контекста.

Следовательно, добавлен by=.EACHI. Теперь, когда мы делаем:

X[Y, .N]
# [1] 3

он делает то, что он должен делать (избегает путаницы). Он возвращает количество строк, полученных в результате соединения.

и

X[Y, .N, by=.EACHI]

оценивает j -выражение совпадающих строк для каждой строки в Y (соответствующее значению из столбцов Y здесь). Было бы проще увидеть это, используя which=TRUE.

X[.(2), which=TRUE] # [1] 4 5
X[.(6), which=TRUE] # [1] 7

Если мы запустим .N для каждого, тогда мы должны получить 2,1.

X[Y, .N, by=.EACHI]
#    x N
# 1: 2 2
# 2: 6 1

Итак, теперь у нас есть обе функции. Надеюсь, это поможет.