我可以在不将 .csv 文件读入内存的情况下对其进行操作吗?

Can I manipulate .csv files without reading them into memory?

提问人:Jay Bee 提问时间:10/24/2023 更新时间:10/24/2023 访问量:90

问:

我有一个 8GB 的 .csv 文件。我尝试以各种方式将其读入 R (, ),但收到一条错误消息:该文件有 200,000 行和大约 1000 列。read.csvfreadcould not allocate memory in C function.

但是,我可以使用 或 参数来查看文件中的变量名称和数据的结构方式。readLinesnrowsread.csv()

如果我知道我需要哪些变量(假设它们是 ,并且在 .csv 中),是否可以根据这些变量过滤 .csv 并将过滤后的数据写入新的(和更小的).csv,而无需将完整数据读取到内存中?weightheightage

我在限制性的虚拟环境中工作,因此使用其他数据库工具或方法具有挑战性。如果可能的话,完全基于 R 的解决方案是可取的。

鉴于这个问题的性质,我不认为完整的 MRE 是可能的,但如果你想要一个用于演示目的的虚拟数据集,我在下面包含了一个。在此示例数据中,我将只选择年龄、体重和身高列,并将它们写入新的 .csv。

structure(list(name = c("Alice", "Bob", "Charlie", "David", "Eve"), 
               age = c(33, 50, 29, 40, 55), 
               weight = c(72, 85, 65, 77, 94), 
               height = c(172, 187, 154, 198, 162), 
               sex = c("Female", "Male", "Male", "Female", "Male")), 
          class = "data.frame", row.names = c(NA, -5L))
r csv

评论

2赞 Hugh 10/24/2023
fread(<file>, select = c("weight", "height", "age"))?
1赞 neilfws 10/24/2023
根据您的操作系统,使用其他工具可能更容易。例如,如果可以在终端中运行:.csvkit 可能是另一种选择。cutcut -d, -f 2,3,4 data.csv > new.csv
1赞 Ben Bolker 10/24/2023
OP 确实说过“如果可能的话,完全基于 R 的解决方案是可取的”......
2赞 lotus 10/24/2023
使用软件包是一种选择吗?它设计用于大于内存的数据集。arrow
0赞 jay.sf 10/24/2023
使用 AWK

答:

4赞 Ben Bolker 10/24/2023 #1

您可以使用以下参数:col_selectvroom::vroom

col_select:要包含在结果中的列。您可以使用相同的 迷你语言作为 'dplyr::select()' 来引用列 名字。使用 'c()' 可使用多个选择表达式。 虽然这种用法不太常见,但“col_select”也接受 数值列索引。完整版见'?tidyselect::language' 有关选择语言的详细信息。

dd <- structure(list(name = c("Alice", "Bob", "Charlie", "David", "Eve"), 
               age = c(33, 50, 29, 40, 55), 
               weight = c(72, 85, 65, 77, 94), 
               height = c(172, 187, 154, 198, 162), 
               sex = c("Female", "Male", "Male", "Female", "Male")), 
          class = "data.frame", row.names = c(NA, -5L))
write.csv(dd, "tmp.csv")
vroom::vroom("tmp.csv", col_select = c("weight", "height", "age"))

@hugh指出,它还具有此功能:data.table::fread()

data.table::fread("tmp.csv", select = c("weight", "height", "age"))

两者都非常快:例如,请参阅此处的基准测试vroomdata.table::fread

为了将数据写回分隔文件(如果你真的想这样做......?vroom::vroom_writedata.table::fwrite