Как выполнить операцию слияния данных.
Примечание: этот вопрос и следующие ответы относятся к версиям data.table < 1.5.3; v. 1.5.3 был выпущен в феврале 2011 года для решения этой проблемы. см. более позднюю обработку (03-2012): Перевод SQL-соединений по внешним ключам в синтаксис R data.table
Я просматривал документацию для data.table package (замена для 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, соединение вызывается аналогично базе:: merge, но использует двоичный поиск на отсортированном ключе". Ясно, что это не так. Могу ли я получить другие столбцы от y в результате x [y] с data.tables? Кажется, что он просто берет строки x, где ключ соответствует ключу y, но игнорирует остальную часть y целиком...
Ответы
Ответ 1
Вы цитируете неправильную часть документации. Если вы посмотрите на документ [.data.table
, вы будете читать:
Когда я является таблицей data.table, x должен иметь ключ, означающий join я to x и return строки в x, соответствующие. Соединиться выполняется между каждым столбцом в я для каждого столбца в ключе xs по порядку. Это похоже на базу R функциональность подстановки матрицы по матрице с двумя столбцами, а в более высоких размеры подмножества n-мерных массив с помощью матрицы n-столбцов
Я признаю, что описание пакета (часть, которую вы цитировали) несколько сбивает с толку, потому что кажется, что "[-операция может использоваться вместо слияния. Но я думаю, что он говорит: если x и y - оба data.tables, мы используем соединение по индексу (которое вызывается как merge) вместо бинарного поиска.
Еще одна вещь:
В библиотеке 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")
EDIT [Ответ больше недействителен]: Этот ответ относится к data.table версии 1.3. В версии 1.5.3 поведение data.table изменено, а x [y] возвращает ожидаемые результаты. Спасибо Мэтью Доуль, автор data.table, для указания на это в комментариях.
Ответ 2
Спасибо за ответы. Я пропустил эту тему, когда она была изначально отправлена. data.table переместилась с февраля. 1.4.1 был выпущен в CRAN некоторое время назад, а 1.5 - в ближайшее время. Например, псевдоним DT() был заменен на list(); как примитив, он намного быстрее, а data.table теперь наследуется от data.frame, поэтому он работает с пакетами, которые принимают только data.frame, такие как ggplot и решетка, без какого-либо преобразования (быстрее и удобнее).
Возможно ли подписаться на тег data.table, чтобы я получил электронное письмо, когда кто-то отправил вопрос с этим тегом? Список datatable-help вырос примерно до 30-40 сообщений в месяц, но я тоже с удовольствием отвечу здесь, если я получу какое-то уведомление.
Мэтью
Ответ 3
Я думаю, что использование функции 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
Что не может стать большой проблемой:)
Ответ 4
Я думаю, что f3lix верен и что документация немного вводит в заблуждение. Преимуществом является быстрое соединение для подмножества данных. Вам все же в конечном итоге необходимо использовать функцию merge
после этого, как в приведенном выше примере.
Вы увидите в презентацию Josh об использовании 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')]