Как сделать операцию слияния 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')]