Как сделать операцию слияния data.table

примечание: этот вопрос и следующие ответы относятся к версиям data.table < 1.5.3; Версия 1.5.3 была выпущена в феврале 2011 года для решения этой проблемы. см. более позднюю обработку (03-2012): перевод SQL-соединений по внешним ключам в синтаксис R data.table


Я копался в документации для пакета data.table (замена data.frame, который гораздо эффективнее для определенных операций), включая презентацию Джоша Райха по SQL и data.table на NYC R Meetup (pdf), но не могу понять эту совершенно тривиальную операцию.

> x <- DT(a=1:3, b=2:4, key='a')
> x
     a b
[1,] 1 2
[2,] 2 3
[3,] 3 4
> y <- DT(a=1:3, c=c('a','b','c'), key='a')
> y
     a c
[1,] 1 a
[2,] 2 b
[3,] 3 c
> x[y]
     a b
[1,] 1 2
[2,] 2 3
[3,] 3 4
> merge(x,y)
  a b c
1 1 2 a
2 2 3 b
3 3 4 c

Документы говорят: "Когда [первый аргумент] сам является data.table, соединение вызывается аналогично base::merge, но использует двоичный поиск по отсортированному ключу". Очевидно, это не тот случай. Могу ли я получить другие столбцы из y в результате x[y] с data.tables? Кажется, что он просто берет строки x, где ключ соответствует ключу y, но полностью игнорирует остальную часть y...

4 ответа

Решение

Вы цитируете не ту часть документации. Если вы посмотрите на документ [.data.table вы будете читать:

Когда я - data.table, x должен иметь ключ, то есть соединять i с x и возвращать строки в x, которые совпадают. Равное соединение выполняется между каждым столбцом в i по каждому столбцу в ключе x по порядку. Это похоже на базовую функциональность R, заключающуюся в подстановке матрицы с помощью матрицы с 2 столбцами и в более высоких измерениях при подстановке n-мерного массива с помощью матрицы с n столбцами.

Я признаю, что описание пакета (часть, которую вы процитировали) несколько сбивает с толку, потому что кажется, что он говорит, что вместо слияния может использоваться операция "[". Но я думаю, что он говорит: если x и y оба являются data.tables, мы используем соединение по индексу (которое вызывается как слияние) вместо бинарного поиска.


Еще кое-что:

Библиотека data.table, которую я установил через install.packages скучал по merge.data.table methodтак что используя merge назвал бы merge.data.frame, После установки пакета от R-Forge R используется быстрее merge.data.table метод.

Вы можете проверить, есть ли у вас метод merge.data.table, проверив вывод:

methods(generic.function="merge")

РЕДАКТИРОВАТЬ [Ответ больше не действителен]: Этот ответ относится к data.table версии 1.3. В версии 1.5.3 поведение data.table изменилось, и x[y] возвращает ожидаемые результаты. Спасибо Matt Dowle, автор data.table, за то, что указал на это в комментариях.

Спасибо за ответы. Я пропустил эту тему, когда она была опубликована. data.table перемещается с февраля. 1.4.1 была выпущена для CRAN некоторое время назад, а 1.5 скоро выйдет. Например, псевдоним DT() был заменен на list(); как примитив, он намного быстрее, а data.table теперь наследуется от data.frame, поэтому он работает с пакетами, которые принимают только data.frame, например, ggplot и lattice, без какого-либо преобразования (быстрее и удобнее).

Можно ли подписаться на тег data.table, чтобы я получал электронное письмо, когда кто-то отправляет вопрос с этим тегом? Список справочных данных увеличился до 30-40 сообщений в месяц, но я рад ответить и здесь, если смогу получить какое-то уведомление.

Мэтью

Я думаю, используя base::merge функция не нужна, так как используя data.table присоединения могут быть намного быстрее. Например, смотрите следующее. я делаю x а также y таблицы данных с 3-3 столбцами:

x <- data.table( foo = 1:5, a=20:24, zoo = 5:1 )
y <- data.table( foo = 1:5, b=30:34, boo = 10:14)
setkey(x, foo)
setkey(y, foo)

И объединить оба с base:merge а также data.table присоединяется, чтобы увидеть скорость казней:

system.time(merge(x,y))
##    user  system elapsed 
##   0.027   0.000   0.023 

system.time(x[,list(y,x)])
##    user  system elapsed 
##   0.003   0.000   0.006 

Результаты не идентичны, так как последний имеет один дополнительный столбец:

merge(x,y)
##      foo  a zoo  b boo
## [1,]   1 20   5 30  10
## [2,]   2 21   4 31  11
## [3,]   3 22   3 32  12
## [4,]   4 23   2 33  13
## [5,]   5 24   1 34  14

x[,list(x,y)]
##      foo  a zoo foo.1  b boo
## [1,]   1 20   5     1 30  10
## [2,]   2 21   4     2 31  11
## [3,]   3 22   3     3 32  12
## [4,]   4 23   2     4 33  13
## [5,]   5 24   1     5 34  14

Который не мог сделать большую проблему:)

Я думаю, что f3lix правильный и что документация немного вводит в заблуждение. Преимущество заключается в быстром объединении данных. Вам все еще нужно использовать merge функционировать впоследствии, как в вашем примере выше.

В презентации Джоша об использовании data.table вы увидите, что именно так работает его пример. Сначала он подставляет один из data.tables, затем выполняет слияние:

library(data.table)
sdt <- DT(series, key='series_id')
ddt <- DT(data, key='series_id')
u <- sdt[ grepl('^[A-Z]{2}URN', fred_id) & !grepl('DSURN', fred_id) ]
d <- ddt[ u, DT(min=min(value)), by='series_id', mult='all']
data <- merge(d,series)[,c('title','min','mean','max')]
Другие вопросы по тегам