R(Windows 上的 64 位):如何解决代码中的 "cannot allocate vector of size 557.6 Mb" 错误

R (64-bit on Windows): How to get around "cannot allocate vector of size 557.6 Mb" error in code

这是 的后续内容,内容是关于如何定位比较两个文本文件之间的特定属性。

多亏了被接受的答案,我在下面的代码中找到了(在我的系统上)适用于较小数据集的代码:

library(tidyverse, data.table)

con1  <- file("file1.csv", open = "r")
con2  <- file("file2.csv", open = "r")

file1 <- select(read.csv(con1, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

setDT(file1)

file2 <- select(read.csv(con2, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

setDT(file2)

full_join(file1, file2, by = "USERID") %>%
  filter(is.na(PROFILE.ID.x) | is.na(PROFILE.ID.y) |
                PROFILE.ID.x != PROFILE.ID.y)

close(con1)
close(con2)

问题: 当 R 开始处理 full_join 函数时,它最终停止并出现错误 cannot allocate vector of size 557.6 Mb.

环境: 这是 Windows 10 OS 和 memory.limit() returns 16222 上的 64 位 R v.3.6.2。我没有加载任何其他对象R 除了上面代码加载的内容。

可能的原因: 问题可能来自于两个 CSV 文件各有大约 120K 行和 83 列。

到目前为止我已经尝试过但没有解决问题:

无论我尝试过什么,错误总是指向“557.6 Mb”。我目前无法为这台机器添加更多 RAM,因为它是公司的笔记本电脑。

问题: 有没有办法以块或其他方式(重写代码)加载文件来解决错误?

我的第一个解决方案是从 file1 和 file2 中删除 USERID 为空的那些行。

根据@r2evans 的评论,这不是一个理想的解决方案(考虑到 merge 可能比 dplyr 中的连接函数对 DT 更友好)。

所以更有效的解决方案可能是用合并替换 full_join,就像这样

merge(file1, file2, by = "USERID", 全部 = TRUE)[is.na(PROFILE.ID.x) | is.na(PROFILE.ID.y) | PROFILE.ID.x != PROFILE.ID.y,]

但我尝试纠正这里问题的第一个解决方案是将 file1 <- filter(file1, USERID != "")file2 <- filter(file2, USERID != "") 行添加到代码中。

最终代码如下所示:

library(tidyverse, data.table)

con1  <- file("file1.csv", open = "r")
con2  <- file("file2.csv", open = "r")

file1 <- select(read.csv(con1, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

file1 <- filter(file1, USERID != "")
setDT(file1)

file2 <- select(read.csv(con2, sep = "|", fill = F, colClasses = "character"),
                PROFILE.ID, USERID)

file2 <- filter(file2, USERID != "")
setDT(file2)

full_join(file1, file2, by = "USERID") %>%
  filter(is.na(PROFILE.ID.x) | is.na(PROFILE.ID.y) |
                PROFILE.ID.x != PROFILE.ID.y)

close(con1)
close(con2)