Причина, по которой t_id = 1
не появляется в выход, потому что прокатный присоединиться принимает строку, в которой ключевой комбинации происходит в последнюю очередь. Из документации (курсив мой):
Относится к последнему присоединиться к колонке, как правило, даты, но могут быть любые упорядоченный переменной, нерегулярные и включая пробелы. Если строка roll = TRUE и i соответствует всем, кроме последнего столбца соединения x, а его значение в последнем столбце соединения падает в промежутке (в том числе после последнего наблюдения в x для этой группы), тогда преобладающее значение in x is свернуто вперед. Эта операция особенно быстро выполняется с использованием модифицированного двоичного поиска . Операция также известна как последнее проведенное наблюдение вперед (LOCF).
Давайте рассмотрим несколько больших массивов данных:
> DT
t_id airport thisTime
1: 1 a 5.1
2: 4 a 5.1
3: 3 a 5.1
4: 2 d 6.2
5: 5 d 6.2
> DT_LU
f_id airport thisTime
1: 1 a 6
2: 2 a 6
3: 2 a 8
4: 1 b 7
5: 1 c 8
6: 2 d 7
7: 1 d 9
При выполнении прокатки присоединиться к так же, как в вашем вопросе:
DT[DT_LU, nomatch=0, roll=Inf]
вы получите:
t_id airport thisTime f_id
1: 3 a 6 1
2: 3 a 6 2
3: 3 a 8 2
4: 5 d 7 2
5: 5 d 9 1
Как вы можете видеть, как с помощью ключа комбинация a, 5.1
и d, 6.2
Последняя строка используется для объединенного типа данных. Поскольку вы используете Inf
в качестве значения рулона, все будущие значения включаются в результирующий тип данных. При использовании:
DT[DT_LU, nomatch=0, roll=1]
вы видите, что только первое значение в будущем включено:
t_id airport thisTime f_id
1: 3 a 6 1
2: 3 a 6 2
3: 5 d 7 2
Если вы хотите f_id
«S для всех комбинаций airport
& thisTime
где DT$thisTime
ниже DT_LU$thisTime
, вы можете достичь этого, создав новую переменную (или заменив существующий thisTime
) с помощью ceiling
функция. Пример, когда я создаю новую переменную thisTime2
, а затем сделать нормальный присоединиться DT_LU
:
DT[, thisTime2 := ceiling(thisTime)]
setkey(DT, airport, thisTime2)[DT_LU, nomatch=0]
, который дает:
t_id airport thisTime thisTime2 f_id
1: 1 a 5.1 6 1
2: 4 a 5.1 6 1
3: 3 a 5.1 6 1
4: 1 a 5.1 6 2
5: 4 a 5.1 6 2
6: 3 a 5.1 6 2
7: 2 d 6.2 7 2
8: 5 d 6.2 7 2
Применительно к данным вы предоставили:
> dt[, thisTime2 := ceiling(thisTime)]
> setkey(dt, airport, thisTime2)[dt_lookup, nomatch=0]
t_id airport thisTime thisTime2 f_id
1: 1 a 5.1 6 1
2: 3 a 5.1 6 1
3: 1 a 5.1 6 2
4: 3 a 5.1 6 2
Если вы хотите включить аль-будущие значения вместо первого пе, вам нужен несколько иной подход, для которого вам понадобится i.col
функциональность (которая еще не задокументированных):
: Сначала установите ключ только airport
столбцов:
setkey(DT, airport)
setkey(DT_LU, airport)
: Используйте i.col
функциональность (которая еще не задокументированных) в j
, чтобы получить то, что вы хотите, следующим образом:
DT1 <- DT_LU[DT, .(tid = i.t_id,
tTime = i.thisTime,
fTime = thisTime[i.thisTime < thisTime],
fid = f_id[i.thisTime < thisTime]),
by=.EACHI]
это дает:
> DT1
airport tid tTime fTime fid
1: a 1 5.1 6 1
2: a 1 5.1 6 2
3: a 1 5.1 8 2
4: a 4 5.1 6 1
5: a 4 5.1 6 2
6: a 4 5.1 8 2
7: a 3 5.1 6 1
8: a 3 5.1 6 2
9: a 3 5.1 8 2
10: d 2 6.2 7 2
11: d 2 6.2 9 1
12: d 5 6.2 7 2
13: d 5 6.2 9 1
Некоторые пояснения: В случае, когда вы присоединяетесь два DataTables, где одни и те же columnnames используются, вы можете обратиться к столбцам DataTable в i
по предшествовавших columnnames с i.
. Теперь можно сравнить thisTime
от DT
с thisTime
от DT_LU
.С помощью by = .EACHI
вы гарантируете, что все комбинации с условием остаются включенными в результирующий тип данных.
В качестве альтернативы, вы можете добиться того же с:
DT2 <- DT_LU[DT, .(airport=i.airport,
tid=i.t_id,
tTime=i.thisTime,
fTime=thisTime[i.thisTime < thisTime],
fid=f_id[i.thisTime < thisTime]),
allow.cartesian=TRUE]
, который дает тот же результат:
> identical(DT1, DT2)
[1] TRUE
Когда вы хотите включить только будущие значения в пределах определенной границы, вы можете использовать:
DT1 <- DT_LU[DT,
{
idx = i.thisTime < thisTime & thisTime - i.thisTime < 2
.(tid = i.t_id,
tTime = i.thisTime,
fTime = thisTime[idx],
fid = f_id[idx])
},
by=.EACHI]
, который дает:
> DT1
airport tid tTime fTime fid
1: a 1 5.1 6 1
2: a 1 5.1 6 2
3: a 4 5.1 6 1
4: a 4 5.1 6 2
5: a 3 5.1 6 1
6: a 3 5.1 6 2
7: d 2 6.2 7 2
8: d 5 6.2 7 2
Когда вы сравниваете это с предыдущим результатом, вы видите, что теперь строки 3, 6, 9, 10 и 12 были удалены.
данных:
DT <- data.table(t_id = c(1,4,2,3,5),
airport = c("a","a","d","a","d"),
thisTime = c(5.1, 5.1, 6.2, 5.1, 6.2),
key=c("airport","thisTime"))
DT_LU <- data.table(f_id = c(rep(1,4),rep(2,3)),
airport = c("a","b","c","d","a","d","e"),
thisTime = c(6,7,8,9,6,7,8),
key=c("airport","thisTime"))
Рад видеть этот пост. Я пытался это сделать в течение некоторого времени. – akrun
Отличное объяснение - «скользящее соединение занимает строку, где сочетается комбинация клавиш» - был ключ к моему пониманию. – tospig
И ваш пример 'потолка' хорошо работает в этой ситуации, но я ожидаю, что это не сработает, когда значение' dt $ thisTime2' будет больше, чем единица времени 1 вдали от значения 'dt_lookup $ thisTime', которое оно пытается совместить к, поэтому мне, возможно, придется придумать альтернативу? – tospig