#r #sas
#r #sas
Вопрос:
Я пытаюсь объединить две очень большие таблицы на основе условного оператора. Я хочу объединить df2 с df1 в каждой группе (x), но включать только строки из df2, которые попадают в минимальные и максимальные значения в df2.
df1 <- data.frame(x = c(1,1,1,1,2,2,2,2,2,3), y = seq(1,10))
df2 <- data.frame(x2 = c(1,1,2,2,2), y_min = c(1, 1, 6, 6, 6), y_max = c(3,3,9,9,9), cat = c("A",'A','S','S','S'))
Результат, который я ищу, это
df3 <- data.frame(x = c(1,1,1,1,2,2,2,2,2,3), y = seq(1,10), y_min = c(1,1,1,NA,NA,6,6,6,6,NA), y_max = c(3,3,3,NA,NA,9,9,9,9,NA), cat = c('A','A','A',NA,NA,'S','S','S','S',NA))
x y y_min y_max cat
1 1 1 1 3 A
2 1 2 1 3 A
3 1 3 1 3 A
4 1 4 NA NA <NA>
5 2 5 NA NA <NA>
6 2 6 6 9 S
7 2 7 6 9 S
8 2 8 6 9 S
9 2 9 6 9 S
10 3 10 NA NA <NA>
Первоначально это было написано в сценарии SAS PROC SQL, но у меня возникли проблемы с преобразованием его в R. Инструкция PROC SQL выглядела примерно так…
PROC SQL;
SELECT a.*, b.*
FROM tbl1 a
LEFT JOIN tbl2 b
on (a.col1 - b.col1) >= 0 and (a.col1 - b.col2) <= 0
and a.id = b.id
Я пробовал использовать base:: amp; data.table::merge, но мне не повезло. Буду признателен за любую помощь.
Ответ №1:
Вы можете использовать пакет sqldf
для использования SQL
кода на R
объектах. В качестве дополнительного примечания ваши имена SAS отличались от имен, которые вы использовали в R, для дальнейшего использования убедитесь, что они совпадают, чтобы люди могли воспроизвести.
library(sqldf)
df1 <- data.frame(x = c(1,1,1,1,2,2,2,2,2,3), y = seq(1,10))
df2 <- data.frame(x2 = c(1,1,2,2,2), y_min = c(1, 1, 6, 6, 6), y_max = c(3,3,9,9,9), cat = c("A",'A','S','S','S'))
sqldf('SELECT a.*, b.*
FROM df1 a
LEFT JOIN df2 b
on (a.y - b.y_min) >= 0 and (a.y- b.y_max) <= 0
and a.x = b.x2')
Ответ №2:
Используя data.table
:
library(data.table)
setDT(df1)
setDT(df2)
unique(df2)[df1,
.(x = i.x, y = i.y, y_min = x.y_min, y_max = x.y_max, cat = x.cat),
on = c("x2 == x", "y_min <= y", "y_max >= y")]
x y y_min y_max cat
1: 1 1 1 3 A
2: 1 2 1 3 A
3: 1 3 1 3 A
4: 1 4 NA NA <NA>
5: 2 5 NA NA <NA>
6: 2 6 6 9 S
7: 2 7 6 9 S
8: 2 8 6 9 S
9: 2 9 6 9 S
10: 3 10 NA NA <NA>
Просто примечание — в нем были повторяющиеся строки df2
, в результате чего простое левое соединение давало больше строк, чем вы указали df3
, отсюда и вызов unique()
.
Комментарии:
1. Для чего используется i? в i.x и i.y?
2. префикс
i.
вj
аргументе adata.table
ссылается на столбцыi
, когдаi
это data.table (как в данном случае). Если вам особенно интересно, ознакомьтесь?data.table
и прочитайте его. Там много, но это очень полезно.3. А, понял, в этом есть смысл! Нужна ли вам часть j, если я просто хочу объединить и сохранить все столбцы?
4. Я полагаю, что по умолчанию он просто сохранит столбцы из
X
(df1
в нашем случае). Впрочем, вы можете это проверить.