从 csv 读取特定(非连续)行
Posted
技术标签:
【中文标题】从 csv 读取特定(非连续)行【英文标题】:Read specific (non-consecutive) rows from csv 【发布时间】:2019-12-20 04:53:15 【问题描述】:我有一个大的 csv 文件,并且只想读取某些行,这些行由要读取的行号向量定义。有没有办法在不将整个 csv 读入内存的情况下读取这些行?
我发现的唯一解决方案似乎允许读取连续行(例如第 2-100 行)。
【问题讨论】:
可以看看sqldf
helps:rdocumentation.org/packages/sqldf/versions/0.4-11/topics/…
@JonnyPhelps 谢谢,我考虑过尝试,但是这些行不容易从 csv 中的数据中子集化,并且希望避免根据是否应选择行向电子表格添加列。
@joran 是的,命令行可能是要走的路,我只是认为 R 中可能有一种快速的方法。
可以使用skip
和nrows
的适当组合来读取单个行(或小块),然后将结果粘合在一起......但可能不会很好。
【参考方案1】:
一个简单的例子,说明如何将我链接到的 sed
方法组合到 R 函数中:
read_rows <- function(file,rows,...)
tmp <- tempfile()
row_cmd <- paste(paste(rows,"p",sep = ""),collapse = ";")
cmd <- sprintf(paste0("sed -n '",row_cmd,"' %s > %s"),file,tmp)
system(command = cmd)
read.table(file = tmp,...)
write.csv(x = mtcars,file = "~/Desktop/scratch/mtcars.csv")
> read_rows(file = "~/Desktop/scratch/mtcars.csv",rows = c(3,6,7),sep = ",",header = FALSE,row.names = 1)
V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
> read_rows(file = "~/Desktop/scratch/mtcars.csv",rows = c(1,5,9),sep = ",",header = TRUE,row.names = 1)
mpg cyl disp hp drat wt qsec vs am gear carb
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
注意与第 1 行作为列标题的区别。
【讨论】:
【参考方案2】:sqldf 会将其读入数据库(它将为您创建然后删除),然后只将您想要的行读入 R。假设在最后的注释中创建的 csv 文件定义所需的 Rows
和然后使用read.csv.sql
。我们为数据库使用了一个临时文件,但如果数据足够小,您可以省略 dbname
参数,它会占用内存。
library(sqldf)
Rows <- c(3, 5, 10)
s <- toString(Rows)
fn$read.csv.sql("Letters.csv", "select * from file where rowid in ($s)",
dbname = tempfile())
给予:
X Letters
1 "3" "c"
2 "5" "e"
3 "10" "j"
如果所需的行数非常大,那么与其在 SQL 语句中嵌入行号,不如从它们创建一个数据框并加入它:
library(sqldf)
Rows <- c(3, 5, 10)
RowsDF <- data.frame(Rows)
s <- toString(Rows)
fn$read.csv.sql("Letters.csv",
"select file.* from file join RowsDF on file.rowid = RowsDF.Rows",
dbname = tempfile())
注意
Letters <- data.frame(Letters = letters, stringsAsFactors = FALSE)
write.csv(Letters, "Letters.csv")
【讨论】:
以上是关于从 csv 读取特定(非连续)行的主要内容,如果未能解决你的问题,请参考以下文章