Может ли кто-нибудь объяснить, как mult работает в data.table, когда он выполняет обновление в соединениях (используя .ИАЧИ и мульт)

#r #join #data.table #left-join

Вопрос:

Я снова пытаюсь понять, как mult работает аргумент при выполнении обновления при соединении. То, что я пытаюсь сделать,-это реализовать левое соединение, как определено в жж.

По соображениям производительности я хотел бы обновить левую таблицу

«Нетривиальная» часть заключается в том, что, когда левая таблица и правая таблица имеют общий столбец (не учитывая столбцы объединения), я хотел бы использовать первое значение в правой таблице для переопределения значения левой таблицы. Я думал mult , что это поможет мне справиться с этой проблемой с несколькими матчами, но я не могу сделать это правильно

 library(data.table)
X <- data.table(x = c("a", "a", "b", "c", "d"), y = c(0, 1, 1, 2, 2), t = 0:4)
X                 
#        x     y     t
#   <char> <num> <int>
#1:      a     0     0
#2:      a     1     1
#3:      b     1     2
#4:      c     2     3
#5:      d     2     4

Y <- data.table(xx = c("f", "b", "c", "c", "e", "a"), y = c(2, NA, 3, 4, 5, 6), u = 2:7)
Y                 
#       xx     y     u
#   <char> <num> <int>
#1:      f     2     2
#2:      b    NA     3
#3:      c     3     4
#4:      c     4     5
#5:      e     5     6
#6:      a     6     7

# Expected result
#        x     y     t                                                 
#   <char> <num> <int>                                                 
#1:      a     6     0    <= single match on xx == "a" so Y[xx == "a", y] is used                                                
#2:      a     6     1    <= single match on xx == "a" so Y[xx == "a", y] is used                                             
#3:      b    NA     2    <= single match on xx == "b" so Y[xx == "b", y] is used                                             
#4:      c     3     3    <= mult match on xx == "c" so Y[xx == "c", y[1L]] is used                                             
#5:      d     2     4    <= no xx == "d" in Y so nothing changes


copy(X)[Y, y := i.y, by = .EACHI, on = c(x = "xx"), mult = "first"][]
#        x     y     t                                                   
#   <char> <num> <int>                                                   
#1:      a     6     0                                                   
#2:      a     1     1   <= a should always have the same value ie 6                                                
#3:      b    NA     2                                                   
#4:      c     4     3   <= y == 4 is not the first value of y in the Y table                                                
#5:      d     2     4                                                   
    
# Using mult = "all" is the closest I get from the right result
copy(X)[Y, y := i.y, by = .EACHI, on = c(x = "xx"), mult = "all"][]
#        x     y     t                                                 
#   <char> <num> <int>                                                 
#1:      a     6     0                                                 
#2:      a     6     1                                                 
#3:      b    NA     2                                                 
#4:      c     4     3    <= y == 4 is not the first value of y in the Y table                                             
#5:      d     2     4  
 

Может ли кто-нибудь объяснить мне, что не так в вышесказанном ?

Я думаю, что я мог бы использовать Y[X, ...] , чтобы получить то, что я хочу, проблема в том, что X очень велик, и производительность, которую я получаю, намного хуже, используя Y[X, ...]

Ответ №1:

Я хотел бы использовать первое значение в правой таблице, чтобы переопределить значение левой таблицы

Выберите первые значения и обновите их самостоятельно:

 X[unique(Y, by="xx", fromLast=FALSE), on=.(x=xx), y := i.y]

   x  y t
1: a  6 0
2: a  6 1
3: b NA 2
4: c  3 3
5: d  2 4
 

fromLast= можно выбрать первую или последнюю строку при отбрасывании дураков.


Как обрабатывается несколько совпадений:

В x[i, mult=] , если строка i имеет несколько совпадений, mult определяет, какие совпадающие строки x выбраны. Это объясняет результаты, показанные в ОП.

In x[i, v := i.v] , если несколько строк i совпадают с одной и той же строкой x , все соответствующие i-строки записываются в x-строку последовательно, поэтому последняя i-строка получает окончательную запись. Включите подробный вывод, чтобы увидеть, сколько изменений внесено в обновление-в этом случае оно превысит количество строк x (поскольку строки редактируются повторно).:

 options(datatable.verbose=TRUE)
data.table(a=1,b=2)[.(a=1, b=3:4), on=.(a), b := i.b][]
# Assigning to 2 row subset of 1 rows
   a b
1: 1 4
 

Комментарии:

1. Спасибо, я видел это на твоем franknarf1.github.io/r-tutorial/_book/tables.html но почему результат изменился, изменив мульт, приводило в замешательство

Ответ №2:

mult всегда равен «последнему» в случае обновления при соединении с :=

Я помню, что это было описано где-то в документации.

Комментарии:

1. В этом случае есть ошибка, как вы можете видеть, изменение mult изменит вывод.

2. Поэтому, пожалуйста, сообщите 🙂