只是一个简单的问题。有没有办法使用read.csv从大文件中导入每个第N行:
示例,一个50-60万行文件,其中您只需要从第2行开始的每第4行。
我想过可能会加入'seq'功能,但我不确定这是否可行。
有什么建议吗?
答案 0 :(得分:14)
对于大型数据文件,最好的选择是在导入R之前过滤掉不必要的行。最简单的方法是通过OS命令,如sed,awk,grep等。以下代码从文件中读取每4行:例如:
write.csv(1:1000, file='test.csv')
file.pipe <- pipe("awk 'BEGIN{i=0}{i++;if (i%4==0) print $1}' < test.csv ")
res <- read.csv(file.pipe)
res
> res
X3 X3.1
1 7 7
2 11 11
3 15 15
4 19 19
5 23 23
6 27 27
7 31 31
8 35 35
答案 1 :(得分:5)
read.csv("filename.csv")[c(FALSE, TRUE, FALSE, FALSE), ]
会做到这一点。
这是有效的,因为逻辑向量被回收,直到它与read.csv
返回的数据帧的行数相匹配。
答案 2 :(得分:4)
正如@ df239建议的那样,使用命令行工具预先过滤行要好得多。
以下是使用sed
的简单版本:
df <- read.csv(pipe("sed -n '2~4p' test.csv"))
2~4p
告诉sed
从第2行开始每隔4行。
答案 3 :(得分:1)
Sven为中等大小的文件提供了很好的答案。但是,如果您这样做的原因是因为读取整个文件并不适合内存,那么您需要采取不同的方法。
使用像Perl或AWK这样的外部工具来预处理文件只能拥有你想要的行可能是最简单的,你可以使用pipe
从另一个程序的输出中读取,这样你就不会必须创建一个中间文件。
另一种方法是将文件传输到数据库,然后只从数据库中选择所需的行。
您也可以循环浏览该文件。如果你明确地打开文件,那么你可以一次读取几行,只保留你想要的那些行,然后从你离开的地方开始读取下一个块。 read.csv
跳过行并限制要读取的行数的选项在这里会有所帮助。
答案 4 :(得分:1)
尽管sed
和awk
解决方案很棒,但最好在R
本身内完成此操作(例如在Windows机器上,或者避免使用GNU sed
vs BSD sed
个差异)。将tidyverse
中的readr::read_*_chunked
与callback一起对每行nth
进行采样的https://github.com/poetix/protonpack一起使用,效果很好:
read_tsv_sample <- function(fn, nth, ...) {
sample_df_cb <- function(df, idx) {
df[seq(1, nrow(df), nth), ]
}
read_tsv_chunked(fn,
...,
chunk_size = 10000,
callback = DataFrameCallback$new(sample_df_cb)
) %>%
bind_rows()
}
例如...
iris %>% write_tsv("iris.tsv")
iris %>% dim
#> [1] 150 5
"iris.tsv" %>%
read_tsv_sample(10,
col_types = cols(.default = col_double())
) %>%
dim
#> [1] 15 5