Как я могу выполнить полные внешние объединения больших наборов данных в 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

Другие вопросы по тегам