关于r:使用适用于大型ffdfs

Using apply on large ffdfs

基本思想是:我有一个很大的ffdf(大约550万x 136个字段)。我知道一个事实,即此数据帧中的某些列中的所有列均为NA。如何找出并删除它们?

我的直觉是做类似的事情(假设dfffdf):

apply(X=is.na(df[,1:136]), MARGIN = 2, FUN = sum)

应该为我提供每列NA计数的向量,然后我可以发现哪些列具有?550万个NA值,使用df <- df[,-c(vector of columns)]删除它们,等等。非常简单。

但是,apply给我一个错误。

1
2
3
4
5
6
7
8
9
10
Error: cannot allocate vector of size 21.6 Mb
In addition: Warning messages:
1: In `[.ff`(p, i2) :
  Reached total allocation of 3889Mb: see help(memory.size)
2: In `[.ff`(p, i2) :
  Reached total allocation of 3889Mb: see help(memory.size)
3: In `[.ff`(p, i2) :
  Reached total allocation of 3889Mb: see help(memory.size)
4: In `[.ff`(p, i2) :
  Reached total allocation of 3889Mb: see help(memory.size)

这告诉我apply无法处理这种大小的数据帧。我可以使用其他替代方法吗?


使用all(is.na(column))更容易。 sapply / lapply不起作用,因为ffdf对象不是列表。

您在代码中使用df[, 1:136]。这将导致ff尝试将所有136列加载到内存中。这是导致内存问题的原因。当您执行df[1:136]时,不会发生这种情况。为最终结果建立索引时,也会发生相同的情况:df <- df[,-c(vector of columns)]将所有选定的列读入内存。

1
2
3
4
5
6
na_cols <- logical(136)
for (i in seq_len(136)) {
  na_cols[i] <- all(is.na(df[[i]]))
}

res <- df[!na_cols]


尝试以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#dummy data
df <- sample(1000000*5)
df <- data.frame( matrix(df,nrow = 1000000))
df$X3 <- NA
df$X6 <- NA

#list of col to remove or keep
colToRemove <- colnames(df)[ colSums(is.na(df[ ,1:6])) == nrow(df) ]
colToKeep <- setdiff(colnames(df), colToRemove)

#subset
res <- df[, colToKeep]

colnames(df)
#[1]"X1""X2""X3""X4""X5""X6"
colnames(res)
#[1]"X1""X2""X4""X5"