我得到了许多不同大小的.csv文件。我选择其中一些在某个条件下对应的(在示例中与我的id
匹配的(。它们是按日期订购的,数量可能很大。我需要知道这些文件的最短和最长日期。
我可以阅读所有需要的,并且只针对列date.hour
,然后我可以很容易地找到所有日期值的最小值和最大值。
但是,如果我能只读取文件的第一行和最后一行,那么它会快得多,因为我对一千个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)`
以下函数将读取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)
}
一般来说,read.table
非常慢。如果您使用readr
库中的read_tsv
、read_csv
或read_delim
,则速度会快得多。
如果你在Linux/Mac操作系统上,你也可以通过设置管道只读取第一部分或最后一部分,无论你的文件有多大,这或多或少都是即时的。假设你没有列标题:
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