#r
#r
Вопрос:
При попытке выполнить следующий анализ с большими данными у меня возникает следующая проблема:
У меня есть два фрейма данных A и B с одним и тем же первичным ключом (по нескольким столбцам), но фрейм данных A дополнительно содержит переменную date.
Теперь я хочу проверить, есть ли для всех уникальных объектов в фрейме данных A запись и в фрейме данных B. Я делаю это с помощью следующей функции:
checkMissing <- function(A, B, primary_key) {
A <- unique(A[,primary_key])
B <- unique(B[,primary_key])
return(A[!A %in% B,])
}
Как оказалось, уникальная часть работает ужасно медленно, когда A получает все больше и больше данных (я проверил что-то вроде 15 миллионов строк, и на моей машине это заняло около 30 секунд).
Есть ли более разумный способ проверить, отсутствуют ли объекты в B, без использования dplyr? (базовый R был бы идеальным, но data.table также работает)
Вот воспроизводимый пример:
library(tictoc)
checkMissing <- function(A, B, primary_key) {
tic("making data unique")
A <- unique(A[,primary_key])
B <- unique(B[,primary_key])
toc()
return(A[!A %in% B,])
}
# creating the dummy key data
ID1 <- 250000
ID2 <- seq(1,ID1/100,1)
ID3 <- seq(1,ID1/10000,1)
tmp <- data.frame("ID1" = seq(1,ID1,1),
"ID2" = sample(ID2, ID1, replace = TRUE),
"ID3" = sample(ID3, ID1, replace = TRUE)
)
#creating the date sequence
dates <- data.frame("date" = seq.Date(as.Date("2019-01-01"),as.Date("2019-02-28"),1))
#cross join to get data frame A
df.A <- merge(dates,tmp,by=NULL)
# create data frame B
df.B <- unique(df.A[,c("ID1","ID2","ID3")])
tic("overall time")
df.result <- checkMissing(df.A,df.B,c("ID1","ID2","ID3"))
toc()
Спасибо!
Стефан
Комментарии:
1. Я думаю, вы ищете средство против объединения? Мои навыки работы с таблицами данных немного подзабыты, но, может быть, это:
setDT(df.A)[!df.B, on = c("ID1","ID2","ID3")]
? Возможно, у меня есть два фрейма данных в обратном порядке, я не уверен. (Также есть функция dplyr anti_join, на случай, если другие люди заинтересуются.)2. Привет @joran, ты прав — это намного быстрее, чем мой первоначальный подход. Спасибо!
Ответ №1:
как отметил джоран в своем комментарии, реализация защиты от объединения в data.table намного быстрее:
setDT(df.A)[!df.B, on = c("ID1","ID2","ID3")]
В моем тесте выполнение данных сократилось с 30-35 секунд до менее чем 2 секунд.
Хотя все еще интересует более быстрая базовая версия R, это правильный ответ.
Лучший Стефан