我正在尝试在 R 中对一组中型数据集进行数据分析。我需要做的一项分析要求我对大约 24-48 个文件进行完全外部连接,每个文件有大约 60 列和多达 450,000 行。所以我经常遇到内存问题。
我认为 ffbase 或 sqldf 会有所帮助,但显然它们中的任何一个都不可能完全外连接。
有解决方法吗?我还没有找到的包裹?
我正在尝试在 R 中对一组中型数据集进行数据分析。我需要做的一项分析要求我对大约 24-48 个文件进行完全外部连接,每个文件有大约 60 列和多达 450,000 行。所以我经常遇到内存问题。
我认为 ffbase 或 sqldf 会有所帮助,但显然它们中的任何一个都不可能完全外连接。
有解决方法吗?我还没有找到的包裹?
这是一个简单的示例,说明了如何对多个数据集进行外部连接:
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", all = T)
外汇
如果您使用的是 ffbase,如果您将 expand.ffgrid 与 merge.ffdf 结合使用,则可以获得所需的完全外连接结果。expand.ffgrid 类似于 expand.grid 但与 ff 向量一起使用,因此它不会溢出您的 RAM,merge.ffdf 允许与另一个 ffdf 合并而不会溢出您的 RAM 并将数据存储在磁盘上。下面是一个例子。
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
这可能有效(注意:关键列必须是每个数据集中的第一列)。
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)
我并不是说它很快,但它可能会克服内存障碍。