Как сделать операцию слияния data.table - PullRequest
49 голосов
/ 10 февраля 2010

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


Я копался в документации для пакета data.table (замена data.frame, который намного эффективнее для определенных операций), включая презентацию Джоша Райха по SQL и данным .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 ]

28 голосов
/ 10 февраля 2010

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

Когда я - data.table, x должен иметь ключ, означающий присоединение i к x и return строки в 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] возвращает ожидаемые результаты. Спасибо Мэтью Доул , автору data.table, за то, что он указал на это в комментариях.

14 голосов
/ 27 июля 2010

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

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

Мэтью

11 голосов
/ 22 января 2011

Я думаю, что использовать функцию base::merge не нужно, поскольку использование data.table объединений может быть намного быстрее Например. смотрите следующее. Я делаю x и y data.tables с 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

Что не могло доставить больших хлопот:)

3 голосов
/ 10 февраля 2010

Я думаю, что 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')]
...