从您之前的(已删除)问题中的test.csv 操作,转换为numeric 后可能会有明显的不同。
为了记录,文件看起来像
996; 1160.32; 1774.51; 4321.05; 2530.97; 2817.63; 1796.18; ...
1008; 1774.51; 1796.18; 1192.42; 1285.69; 1225.96; 2229.92; ...
1020; 1796.18; 1285.69; 711.67; 1761.44; 1016.74; 1671.90; ...
1032; 1285.69; 1761.44; 1016.74; 1671.90; 725.51; 2466.49; ...
1044; 1761.44; 1016.74; 725.51; 2466.49; 661.82; 1378.85; ...
1056; 1761.44; 1016.74; 2466.49; 661.82; 1378.85; 972.94; ...
1068; 2466.49; 661.82; 1378.85; 972.94; 2259.46; 3648.49; ...
1080; 2466.49; 1378.85; 972.94; 2259.46; 1287.72; 1074.63; ...
虽然真正的 test.csv 有 751 行文本,并且每行有 10001-10017 之间的 ; 分隔字段。这个(未删节的)文件不到 64 MiB。
读入、解析,然后转换为数字对其对象大小有显着影响:
object.size(aa1 <- readLines("test.csv"))
# Warning in readLines("test.csv") :
# incomplete final line found on 'test.csv'
# 67063368 bytes
object.size(aa2 <- strsplit(aa1, "[; ]+"))
# 476021832 bytes
object.size(aa3 <- lapply(aa2, as.numeric))
# 60171040 bytes
我们最终得到:
length(aa3)
# [1] 751
str(aa3[1:4])
# List of 4
# $ : num [1:10006] 996 1160 1775 4321 2531 ...
# $ : num [1:10008] 1008 1775 1796 1192 1286 ...
# $ : num [1:10009] 1020 1796 1286 712 1761 ...
# $ : num [1:10012] 1032 1286 1761 1017 1672 ...
因此,将其读入全长字符串不会导致内存爆炸,而是将其拆分为每行 10000 多个字段。这是因为每个 character 对象的开销更大/em>:
### vec-1, nchar-0
object.size("")
# 112 bytes
### vec-5, nchar-0
object.size(c("","","","",""))
# 152 bytes
### vec-5, nchar-10
object.size(c("aaaaaaaaaa","aaaaaaaaaa","aaaaaaaaaa","aaaaaaaaaa","aaaaaaaaaa"))
# 160 bytes
如果我们查看原始数据,我们会看到爆炸式增长:
object.size(aa1[1]) # whole lines at a time, so one line is 10000+ characters
# 89312 bytes
object.size(aa2[[1]]) # vector of 10000+ strings, each between 3-8 characters
# 633160 bytes
但幸运的是,内存中的数字要小得多:
object.size(1)
# 56 bytes
object.size(c(1,2,3,4,5))
# 96 bytes
而且它的扩展性要好得多。显然,在 R 的存储中将数据从 453MiB(拆分,字符串)减少到 57MiB(拆分,数字)就足够了。
在读取这些文件时,您仍然会看到 R 的内存使用量激增。您可以尝试通过在strsplit 之后立即转换为数字来减少它;老实说,我不知道 R 的垃圾收集器(高级编程语言的常见事物)会以多快的速度返回内存,我也不确定根据 R 的 "global string pool" 这将如何表现。但是如果你有兴趣,你可以试试这个你的函数的改编。
func <- function(path) {
aa1 <- readLines(path)
aa2 <- lapply(aa1, function(st) as.numeric(strsplit(st, "[; ]+")[[1]]))
aa2
}
(我不保证它不会仍然“增加”你的内存使用量,但也许它不会那么糟糕。)
然后你的 for 循环的规范替换(虽然那个循环很好)是
dat <- lapply(files, func)