Как я могу выполнить полные внешние объединения больших наборов данных в R?
Я пытаюсь провести анализ данных в R на группе наборов данных среднего размера. Один из анализов, которые мне нужно сделать, требует от меня полного внешнего объединения примерно из 24-48 файлов, каждый из которых имеет около 60 столбцов и до 450 000 строк. Так что я много сталкиваюсь с проблемами с памятью.
Я думал, что в ffbase или sqldf это поможет, но, по-видимому, полное внешнее объединение невозможно ни с одним из них.
Есть ли обходной путь? Пакет, который я еще не нашел?
4 ответа
Вот простой пример, который иллюстрирует, как сделать внешние объединения нескольких наборов данных:
library(sqldf)
dat1 <- data.frame(x = 1:5,y = letters[1:5])
dat2 <- data.frame(w = 3:8,z = letters[3:8])
>
> sqldf("select * from dat1 left outer join dat2 on dat1.x = dat2.w UNION
+ select * from dat2 left outer join dat1 on dat1.x = dat2.w")
x y w z
1 1 a NA <NA>
2 2 b NA <NA>
3 3 c 3 c
4 4 d 4 d
5 5 e 5 e
6 6 f NA <NA>
7 7 g NA <NA>
8 8 h NA <NA>
Вот оно, полное внешнее объединение, использующее sqldf и SQLite в качестве бэкэнда.
Как я уже упоминал, sqldf поддерживает больше серверных частей, чем SQLite. Один поиск в Google показывает, что полные внешние объединения выполняются точно так же, как и в MySQL. Я менее знаком с postgres, но этот вопрос наверняка предполагает, что там также возможны полные внешние соединения.
Без sqldf вот умное и простое решение:
объединить (a, b, by = "col", все = T)
FX
Это может сработать (примечание: ключевой столбец должен быть первым столбцом в каждом наборе данных).
library(ff)
library(ffbase)
fullouterjoin <- function(ffdf1, ffdf2){
# do a left outer join
leftjoin <- merge(ffdf1, ffdf2, by = "key", all.x = TRUE)
# do a right outer join (it's just a left outer join with the objects swapped)
rightjoin <- merge(ffdf2, ffdf1, by = "key", all.x = TRUE)
# swap the column orders (make ffd1 columns first and ffd2 columns later)
srightjoin <- rightjoin[c(names(ffdf1), names(ffdf2)[2:length(ffdf2)])]
# stack left outer join on top of the (swapped) right outer join
stacked <- rbind(leftjoin, srightjoin)
# remove duplicate rows
uniques <- unique(stacked)
# that's it
return(uniques)
}
использование:
newffdf <- fullouterjoin(some_ffdf, another_ffdf)
Я не говорю, что это быстро, но это может преодолеть барьер памяти.
Если вы используете ffbase, вы можете получить желаемый результат полного внешнего соединения, если объедините файл expand.ffgrid с merge.ffdf. expand.ffgrid похож на expand.grid, но работает с векторами ff, поэтому он не будет перегружать вашу оперативную память, а merge.ffdf позволяет объединяться с другими файлами ffdf без перегрузки вашей оперативной памяти и сохранения данных на диске. Пример ниже.
require(ffbase)
x <- ffseq(1, 10000)
y <- ff(factor(LETTERS))
allcombinations <- expand.ffgrid(x, y)
addme <- data.frame(Var1 = c(1, 2), Var2 = c("A","B"), measure = rnorm(2))
addme <- as.ffdf(addme)
myffdf <- merge(allcombinations, addme, by.x=c("Var1","Var2"), by.y=c("Var1","Var2"), all.x=TRUE)
myffdf[1:10,]
Далее рассмотрим удаление строк из пакета ff, чтобы узнать, как создать подмножество myffdf.
Посмотрите на? Ffbase::expand.ffgrid и? Ffbase::merge.ffdf