从文件中读取特定列到R中的方法是什么?(在“read.table”和“scan”之间找到一个适当的平衡点?)

44
我有一些非常大的分隔数据文件,我想在 R 中仅处理某些列,而不需要花费时间和内存来创建整个文件的 data.frame
我所知道的唯一选项是 read.table,但当我只需要几列数据时,这种方法非常浪费资源,或者使用 scan,但这似乎对我想要实现的功能过于底层。
是否有更好的选择,无论是纯 R 还是通过调用其他 shell 脚本来执行列提取,然后对其输出使用 scan 或 read.table?(这将引出一个问题,如何在R中调用shell脚本并捕获其输出?)

1
这里有一整套有用的答案。其中任何一个都可以在特定情况下提供帮助。被接受的答案只是最接近我的实际情况,并包含了代码片段。(我本来也可以选择Dirk,但他似乎已经有足够的声誉了;-)) - Alex Stoddard
7
最佳答案在新问题中,链接为https://dev59.com/pm025IYBdhLWcg3wzZT3。 - Marek
4个回答

35
有时当我有一个以制表符分隔的文件中的数据时,我会像这样做:
df <- read.table(pipe("cut -f1,5,28 myFile.txt"))

这使得cut可以进行数据选择,而且几乎不需要使用太多内存。

有关纯R版本的内容,请参见仅读取有限列,在read.table中的colClasses参数中使用"NULL"


1
你的第一个例子几乎就是我最终采用的方法(我的情况中使用了 awk 而不是 cut,因为文件格式有点不规则)。就我理解而言,你的第二个例子并不完全等价。它难道不会创建整个 data.frame 然后再将其丢弃吗?当我想要从一百万行文件中选择其中的10列中的2列时,这在性能上会有很大的差异。 - Alex Stoddard
12
不,纯R的等效写法应该是(假设有28个列): mycols <- rep(NULL, 28); mycols[c(1,5,28)] <- NA; df <- read.table(file, colClasses=mycols) - Dirk Eddelbuettel
2
@DirkEddelbuettel 我刚刚偶然发现了这个。似乎需要将NULL放在引号中。 - RJ-
我喜欢@DirkEddelbuettel提供的解决方案,但是对于.@RJ,我必须将NULL放在引号中。 'mycols <- rep("NULL", 28)' - Tom Evans
如果文件名在我的R变量中(因此我无法使用固定的“myFile.txt”),该怎么办? - Perlnika
显示剩余2条评论

19

有一种可能的方法是使用pipe()代替文件名,并且使用awk或类似过滤器提取您想要的列。

有关pipe和相关内容,请参见help(connection)

编辑:如果您非常明确地指定colClasses,那么read.table()也可以为您完成这项工作——对于给定列的NULL值跳过该列。请参阅help(read.table)。因此,在基本的R中我们就有了一个无需额外包或工具的解决方案。


8

我认为Dirk的方法既直接又快速。我使用的另一种方法是将数据加载到sqlite中,它比read.table()加载速度要快得多,然后只提取你想要的内容。sqldf()包使这一切变得非常容易。这里是之前Stack Overflow的一个答案链接,其中提供了sqldf()的代码示例。


3

这可能比你需要的多,但如果你处理的是非常大的数据集,那么你也可以看看HadoopStreaming包,它提供了一个使用Hadoop的map-reduce例程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接