1

我正在尝试通过合并和附加两个现有的 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

我希望这能让我更清楚我试图实现的目标。

4

2 回答 2

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"
于 2014-01-27T12:54:28.530 回答
0

以下答案似乎不适用于大型ffdf对象(1E8 记录)。在最初将其中的一部分作为评论发布后,我决定将其作为答案发布,因为代码可能是工作答案的起点。

一个技巧是首先使用例如 smartmatch 合并两个 ffdf 的一小部分。然后调整此对象的大小以适合 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

但是,在实际尺寸上测试时,ffdfncol(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
于 2014-01-27T08:28:02.643 回答