Как выполнить операцию слияния данных.

Примечание: этот вопрос и следующие ответы относятся к версиям 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')]