Ответ 1
Вы можете попробовать это:
# used data
# set the key in 'B' to the column which you use to join
A <- data.table(a = 1:4, b = 12:15)
B <- data.table(a = 2:3, b = 13:14, key = 'a')
B[A]
Предположим, что у меня есть два data.table's:
А:
A B
1: 1 12
2: 2 13
3: 3 14
4: 4 15
В:
A B
1: 2 13
2: 3 14
и у меня есть следующий код:
merge_test = merge(dataA, dataB, by="A", all.data=TRUE)
Я получаю:
A B.x B.y
1: 2 13 13
2: 3 14 14
Тем не менее, я хочу, чтобы все строки в dataA в финальной объединенной таблице. Есть ли способ сделать это?
Вы можете попробовать это:
# used data
# set the key in 'B' to the column which you use to join
A <- data.table(a = 1:4, b = 12:15)
B <- data.table(a = 2:3, b = 13:14, key = 'a')
B[A]
Если вы хотите добавить значения b
для B
в A
, то лучше всего объединить A
с B
и обновить A
по ссылке следующим образом:
A[B, on = 'a', bb := i.b]
который дает:
> A a b bb 1: 1 12 NA 2: 2 13 13 3: 3 14 14 4: 4 15 NA
Это лучший подход, чем использование B[A, on='a']
поскольку последний просто выводит результат на консоль. Если вы хотите вернуть результаты обратно в A
, вам нужно использовать A <- B[A, on='a']
что даст вам тот же результат.
Причина, по которой A[B, on = 'a', bb := ib]
лучше, чем A <- B[A, on = 'a']
заключается в эффективности использования памяти. При A[B, on = 'a', bb := ib]
расположение A
в памяти остается неизменным:
> address(A) [1] "0x102afa5d0" > A[B, on = 'a', bb := i.b] > address(A) [1] "0x102afa5d0"
С другой стороны, с A <- B[A, on = 'a']
, новый объект создается и сохраняется в памяти как A
и, следовательно, имеет другое место в памяти:
> address(A) [1] "0x102abae50" > A <- B[A, on = 'a'] > address(A) [1] "0x102aa7e30"
Использование merge
(merge.data.table
) приводит к аналогичному изменению расположения в памяти:
> address(A) [1] "0x111897e00" > A <- merge(A, B, by = 'a', all.x = TRUE) > address(A) [1] "0x1118ab000"
Таким образом, для эффективности памяти лучше использовать синтаксис "update-by-reference-join":
A[B, on = 'a', bb := i.b]
Хотя это не имеет заметного различия с такими маленькими наборами данных, оно имеет значение для больших наборов данных, для которых был разработан data.table
.
Вероятно, также стоит упомянуть, что порядок A
остается прежним.
Чтобы увидеть влияние на скорость и использование памяти, сделайте бенчмаркинг с некоторыми большими наборами данных (данные см. Во 2-й части используемого раздела данных ниже):
library(bench)
bm <- mark(AA <- BB[AA, on = .(aa)],
AA[BB, on = .(aa), cc := cc],
iterations = 1)
который дает (показаны только соответствующие измерения):
> bm[,c(1,3,5)] # A tibble: 2 x 3 expression median mem_alloc <bch:expr> <bch:tm> <bch:byt> 1 AA <- BB[AA, on = .(aa)] 4.98s 4.1GB 2 AA[BB, on = .(aa), ':='(cc, cc)] 560.88ms 384.6MB
Таким образом, в этой настройке "обновление по ссылке-соединение" происходит примерно в 9 раз быстрее и потребляет в 11 раз меньше памяти.
ПРИМЕЧАНИЕ. Увеличение скорости и использование памяти могут различаться в разных настройках.
Используемые данные:
# initial datasets
A <- data.table(a = 1:4, b = 12:15)
B <- data.table(a = 2:3, b = 13:14)
# large datasets for the benchmark
set.seed(2019)
AA <- data.table(aa = 1:1e8, bb = sample(12:19, 1e7, TRUE))
BB <- data.table(aa = sample(AA$a, 2e5), cc = sample(2:8, 2e5, TRUE))