我试图通过合并和附加两个现有的ffdf数据帧来创建ffdf数据帧。 ffdfs具有不同数量的列和不同的行号。我知道merge()
只执行内部和外部连接,而ffdfappend()
如果列不相同则不允许附加。我想知道是否有人有解决方法。功能类似于smartbind()
中的gtools package
功能或任何其他解决方法。
当然,由于ffdfs的大小,转换回as.data.frame()
并使用smartbind()
不是一个选项。
非常感谢任何帮助。
编辑:根据建议,这是一个可重复的例子:
require(ff)
require(ffbase)
df1 <- data.frame(A=1:10, B=LETTERS[1:10], C=rnorm(10), G=1 )
df2 <- data.frame(A=11:20, D=rnorm(10), E=letters[1:10], G=1 )
ffdf1 <- as.ffdf(df1)
ffdf2 <- as.ffdf(df2)
期望的结果看起来应该是这样的(在data.frames上生成,如果我知道如何在ffdfs上生成它我不会问这个问题):
require(gtools)
dfcombined <- smartbind(df1, df2)
dfcombined
A B C G D E
1:1 1 A 1.1556719 1 NA <NA>
1:2 2 B 0.3279260 1 NA <NA>
1:3 3 C 0.4067643 1 NA <NA>
1:4 4 D -0.9144717 1 NA <NA>
1:5 5 E -0.1138263 1 NA <NA>
1:6 6 F 0.8227560 1 NA <NA>
1:7 7 G 0.3394098 1 NA <NA>
1:8 8 H 1.4498439 1 NA <NA>
1:9 9 I -1.3202419 1 NA <NA>
1:10 10 J 0.2099266 1 NA <NA>
2:1 11 <NA> NA 1 -1.5802636 a
2:2 12 <NA> NA 1 1.2925790 b
2:3 13 <NA> NA 1 1.3477483 c
2:4 14 <NA> NA 1 -1.6760211 d
2:5 15 <NA> NA 1 0.1456295 e
2:6 16 <NA> NA 1 0.4726867 f
2:7 17 <NA> NA 1 -1.5209117 g
2:8 18 <NA> NA 1 0.3407136 h
2:9 19 <NA> NA 1 1.3582868 i
2:10 20 <NA> NA 1 -1.5083929 j
我希望这能让我更清楚我想要实现的目标。
答案 0 :(得分:0)
以下答案似乎不适用于大ffdf
个对象(1E8记录)。在最初将其中的一部分作为评论发布后,我决定将其作为答案发布,因为代码可能是工作答案的起点。
一个技巧是首先合并两个ffdf的一小部分,例如smartmatch。然后调整此对象的大小以适合ffdf1和ffdf2。将ffdf1复制到此对象的前半部分,将ffdf2复制到第二部分:
require(gtools)
dfcombined <- as.ffdf(smartbind(ffdf1[1,], ffdf2[1,]))
nrow(dfcombined) <- nrow(ffdf1) + nrow(ffdf2)
# insert ffdf1 into dfcombined
cols1a <- names(dfcombined)[names(dfcombined) %in% names(ffdf1)]
cols1b <- names(dfcombined)[!(names(dfcombined) %in% names(ffdf1))]
dfcombined[ri(1, nrow(ffdf1)), cols1a] <- ffdf1
dfcombined[ri(1, nrow(ffdf1)), cols1b] <- NA
# insert ffdf2 into dfcombined
cols2a <- names(dfcombined)[names(dfcombined) %in% names(ffdf2)]
cols2b <- names(dfcombined)[!(names(dfcombined) %in% names(ffdf2))]
dfcombined[ri(nrow(ffdf1)+1, nrow(dfcombined)), cols2a] <- ffdf2
dfcombined[ri(nrow(ffdf1)+1, nrow(dfcombined)), cols2b] <- NA
但是,在真实大小ffdf
上测试时,ncol(dfcombined) <- ...
行会生成错误
> ffdf1 <- ffdf(
+ a = ffrandom(1E8, rnorm),
+ b = ffrandom(1E8, rnorm)
+ )
> ffdf2 <- ffdf(
+ b = ffrandom(1E8, rnorm),
+ c = ffrandom(1E8, rnorm)
+ )
> dfcombined <- as.ffdf(smartbind(ffdf1[1,], ffdf2[1,]))
>
> nrow(dfcombined) <- nrow(ffdf1) + nrow(ffdf2)
Error: cannot allocate vector of size 762.9 Mb
答案 1 :(得分:0)
如果您正在寻找像rbind.fill
这样的东西,但对于ffdf对象。也许这就是你要找的东西。在Jan准备的测试示例中,这对我没有记忆问题。
require(ff)
require(ffbase)
smartffdfbind <- function(..., clone=TRUE){
x <- list(...)
columns <- lapply(x, FUN=function(x) colnames(x))
columns <- do.call(c, columns)
columns <- unique(columns)
for(element in 1:length(x)){
missingcolumns <- setdiff(columns, colnames(x[[element]]))
for(missingcolumn in missingcolumns){
x[[element]][[missingcolumn]] <- ff(NA, vmode = "logical", length = nrow(x[[element]]))
}
}
if(clone){
result <- clone(x[[1]][columns])
}else{
result <- x[[1]][columns]
}
for (l in tail(x, -1)) {
result <- ffdfappend(result[columns], l[columns], recode=TRUE)
}
result
}
ffdf1 <- ffdf(a = ffrandom(1E8, rnorm), b = ffrandom(1E8, rnorm))
ffdf2 <- ffdf(b = ffrandom(1E8, rnorm), c = ffrandom(1E8, rnorm))
x <- smartffdfbind(ffdf1, ffdf2)
nrow(x)
[1] 200000000
class(x)
"ffdf"