Ответ 1
Причина, по которой t_id = 1
не отображается в выходном файле, состоит в том, что скользящее соединение принимает строку, в которой ключевая комбинация имеет последнее значение. Из документации (основное внимание):
Относится к последнему столбцу объединения, обычно к дате, но может быть любым упорядоченная переменная, нерегулярная и включая пробелы. Если roll = TRUE и я строка соответствует всем, кроме последнего столбца соединения x, и его значение в последний столбец присоединяется к пробелу (в том числе после последнего наблюдение в x для этой группы), то преобладающее значение в x равно свернул вперед. Эта операция особенно быстро используется с измененным двоичный поиск. Операция также известна как последнее наблюдение вперед (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
как значение roll-value, все будущие значения включаются в результирующий тип данных. Когда вы используете:
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
для всех комбинаций 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
Если вы хотите включить al в будущие значения вместо первого, вам понадобится несколько другой подход, для которого вам понадобится i.col
функциональность (которая еще не задокументирована):
1: сначала установите только столбцы airport
:
setkey(DT, airport)
setkey(DT_LU, airport)
2. Используйте 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
Некоторое объяснение: если вы присоединяетесь к двум типам данных, где используются одни и те же имена столбцов, вы можете ссылаться на столбцы данных в i
, предшествуя именам столбцов с помощью i.
. Теперь можно сравнить thisTime
с DT
с thisTime
с DT_LU
. С помощью by = .EACHI
вы гарантируете, что все комбинации с условием выполнены в результирующем datatable.
В качестве альтернативы вы можете добиться того же:
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"))