Using apply on large ffdfs
基本思想是:我有一个很大的ffdf(大约550万x 136个字段)。我知道一个事实,即此数据帧中的某些列中的所有列均为NA。如何找出并删除它们?
我的直觉是做类似的事情(假设df是ffdf):
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无法处理这种大小的数据帧。我可以使用其他替代方法吗?
- 只是df[, !colSums(is.na(df[,1:136]))==nrow(df)]怎么样?
-
@ zx8754您的意思是colSums(请参阅我以前的编辑)吗?无论哪种方式,我仍然会遇到相同的错误。
-
@ zx8754刚刚看到您的编辑,将尝试
-
@ zx8754但是,我也会有兴趣获取被删除的列的列表,但是我想那不会太困难..只需比较names。
使用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] |
- 声明cols时出现类似错误:Warning messages: 1: In ff:: [。ff (x = x, i = i, pack = pack) : Reached total allocation of 3889Mb: see help(memory.size) 2: In ff:: [。ff (x = x, i = i, pack = pack) : Reached total allocation of 3889Mb: see help(memory.size)
-
@竖笛演奏家我在您的问题下的评论中看到了讨论,并修改了我的答案。导致您的错误是因为您的代码将完整的数据集读取到内存中。
-
cols起作用,df[, !cols]给了我类似的错误。
-
我不确定这是否是意图,但是cols只有两个值:virtual:FALSE下和physical:FALSE下。
-
@单簧管你是对的。 sapply不起作用。我用来测试代码的玩具示例可以正常工作,因为我不小心碰巧拥有与sapply返回的相同数量的列。我的新代码无法正常工作。
-
非常好。谢谢!
尝试以下示例:
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" |