Условное объединение в r
Я хотел бы условно соединить две таблицы данных вместе:
library(data.table)
set.seed(1)
key.table <-
data.table(
out = (0:10)/10,
keyz = sort(runif(11))
)
large.tbl <-
data.table(
ab = rnorm(1e6),
cd = runif(1e6)
)
в соответствии со следующим правилом: соответствие наименьшему значению out
в key.table
, значение keyz
которого больше cd
. У меня есть следующее:
library(dplyr)
large.tbl %>%
rowwise %>%
mutate(out = min(key.table$out[key.table$keyz > cd]))
который обеспечивает правильный вывод. Проблема в том, что операция rowwise
кажется дорогой для large.tbl
, которую я фактически использую, сбой ее, если она не находится на определенном компьютере. Есть ли меньше операций, связанных с памятью? Следующее выглядит немного быстрее, но недостаточно для проблемы, которую у меня есть.
large.tbl %>%
group_by(cd) %>%
mutate(out = min(key.table$out[key.table$keyz > cd]))
Это пахнет проблемой с ответом data.table
, но ответ не должен использовать этот пакет.
Ответы
Ответ 1
Что вы хотите:
setkey(large.tbl, cd)
setkey(key.table, keyz)
key.table[large.tbl, roll = -Inf]
См. ?data.table
> roll
:
Применяется к последнему столбцу объединения, обычно к дате, но может быть любой упорядоченной переменной, нерегулярной и включающей пробелы. Если строка roll=TRUE
и i
соответствует всем, кроме последнего столбца столбца x
, а его значение в последнем столбце столбца i
попадает в пробел (в том числе после последнего наблюдения в x
для этой группы), тогда преобладающее значение в x
выполняется вперед. Эта операция особенно быстро используется с измененным двоичным поиском. Операция также известна как последнее наблюдение, перенесенное вперед (LOCF). Обычно в x
не должно быть дубликатов, последний ключевой столбец - дата (или время или дата-время) и все столбцы ключа x
. Общей идиомой является выбор одновременного регулярного временного ряда (dts
) по набору идентификаторов (ids
): DT[CJ(ids,dts),roll=TRUE]
, где DT
имеет ключ с двумя столбцами (id,date
) и CJ
выступает для перекрестного соединения. Когда roll
- это положительное число, это ограничивает перенос дальнейших значений. roll=TRUE
эквивалентно roll=+Inf
. Когда roll
- отрицательное число, значения откатываются назад; т.е. последующее наблюдение переносится назад (NOCB). Используйте -Inf
для неограниченного возврата назад. Когда roll "nearest"
, ближайшее значение объединяется.
(честно говоря, я думаю, что это может пойти на некоторое разъяснение, оно довольно плотное)
Ответ 2
Если key.table$out
также сортируется, как в примере с вашей игрушкой, следующие будут работать
ind <- findInterval(large.tbl$cd, key.table$keyz) + 1
large.tbl$out <- key.table$out[ind]
head(large.tbl)
# ab cd out
#1: -0.928567035 0.99473795 NA
#2: -0.294720447 0.41107393 0.5
#3: -0.005767173 0.91086585 1.0
#4: 2.404653389 0.66491244 0.8
#5: 0.763593461 0.09590456 0.1
#6: -0.799009249 0.50963409 0.5
Если key.table$out
не сортируется,
ind <- findInterval(large.tbl$cd, key.table$keyz) + 1
vec <- rev(cummin(rev(key.table$out)))
large.tbl$out <- vec[ind]