我有许多不同大小的.csv文件。我选择了一些符合条件的(在示例中与我的id
匹配)。它们按日期排序,并且可能很大。我需要知道这些文件的最小和最大日期。
我可以读取所有想要的,并且只读取date.hour
列,然后可以轻松找到所有日期值的最小值和最大值。
但是如果我只能读取文件的第一行和最后一行,则将更快,因为我重复了1000个id。
有人知道如何解决这个问题吗?
此代码运行良好,但我希望对其进行改进。
`read.tables.simple <- function(file.names, ...) {require(plyr)
ldply(file.names, function(fn) data.frame(read.table(fn, ...)))}`
`diri <- dir()
dat <- read.tables.simple(diri[1], header = TRUE, sep = ";", colClasses = "character")
colclass <- rep("NULL", ncol(dat))
x <- which(colnames(dat) == "date.hour")
colclass[x] <- "character"
x <- grep("id", diri)
dat <- read.tables.simple(diri[x], header = TRUE, sep = ";", colClasses = colclass)
datmin <- min(dat$date.hour)
datmax <- max(dat$date.hour)`
[通常,read.table
非常慢。如果您使用read_tsv
库中的read_csv
,read_delim
或readr
,则速度会快很多。
如果您使用的是Linux / Mac OS,则还可以通过设置管道来仅读取第一部分或最后一部分,无论文件多大,该管道都会或多或少地立即生效。假设您没有列标题:
library(readr)
read_last <- function(file) {
read_tsv(pipe(paste('tail -n 1', file)), col_names=FALSE)
}
# Readr can already read only a select number of lines, use `n_max`
first <- read_tsv(file, n_max=1, col_names=FALSE)
[如果要进行并行处理,甚至可以并行读取文件,请参见例如library(parallel)
和?mclapply
以下函数将读取csv的前两行(标头行和第一数据行),然后seek
到文件末尾并读取最后一行。然后它将这三行粘贴在一起,以两行csv的形式读取它们,并从中返回列date.time
。这是您的最小值和最大值,因为时间是按顺序排列的。
您需要告诉函数最大行长。如果您高估了这一点也可以,但是请确保该数字小于文件大小的三分之一。
read_head_tail <- function(file_path, line_length = 100)
{
con <- file(file_path)
open(con)
seek(con, where = 0)
first <- suppressWarnings(readChar(con, nchars = 2 * line_length))
first <- strsplit(first, "\n")[[1]][1:2]
seek(con, where = file.info(file_path)$size - line_length)
last <- suppressWarnings(readChar(con, nchars = line_length))
last <- strsplit(last, "\n")[[1]]
last <- last[length(last)]
close(con)
csv <- paste(paste0(first, collapse = "\n"), last, sep = "\n")
df <- read.csv(text = csv, stringsAsFactors = FALSE)[-1]
return(df$date.hour)
}