如何使用fread函数读取特定的CSV文件行

时间:2014-02-15 14:38:06

标签: r csv io performance

我有一个大的双文件(1000万乘500)的CSV文件,我只想阅读这个文件的几千行(在1到1千万之间的不同位置),由二进制向量{{1长度为1000万,如果我不想读取行,则假设值为V,如果我想读取该行则为0

如何从1包中获取io函数fread来执行此操作?我问,因为data.table与所有其他io方法相比如此之快。

此问题的最佳解决方案Reading specific rows of large matrix data file提供了以下解决方案:

fread

其中read.csv( pipe( paste0("sed -n '" , paste0( c( 1 , which( V == 1 ) + 1 ) , collapse = "p; " ) , "p' C:/Data/target.csv" , collapse = "" ) ) , head=TRUE)是大型CSV文件,C:/Data/target.csvV0的向量。

但是我注意到,这比仅在整个矩阵上使用1要慢几个数量级,即使fread仅对于V只有一小部分总行数。

因此,由于整个矩阵上的1将主导上述解决方案,我如何将fread(特别是fread)与行采样结合起来?

这不是重复,因为它只是关于函数fread

这是我的问题设置:

fread

1 个答案:

答案 0 :(得分:4)

此方法采用向量v(对应于您的read_vec),标识要读取的行序列,将这些行提供给fread(...)的连续调用,以及rbinds结果一起。

如果您想要的行随机分布在整个文件中,这可能不会更快。但是,如果行是块状(例如c(1:50, 55, 70, 100:500, 700:1500)),那么对fread(...)的调用很少,您可能会看到显着的改进。

# create sample dataset
set.seed(1)
m   <- matrix(rnorm(1e5),ncol=10)
csv <- data.frame(x=1:1e4,m)
write.csv(csv,"test.csv")
# s: rows we want to read
s <- c(1:50,53, 65,77,90,100:200,350:500, 5000:6000)
# v: logical, T means read this row (equivalent to your read_vec)
v <- (1:1e4 %in% s)

seq  <- rle(v)
idx  <- c(0, cumsum(seq$lengths))[which(seq$values)] + 1
# indx: start = starting row of sequence, length = length of sequence (compare to s)
indx <- data.frame(start=idx, length=seq$length[which(seq$values)])

library(data.table)
result <- do.call(rbind,apply(indx,1, function(x) return(fread("test.csv",nrows=x[2],skip=x[1]))))