читать только первый и последний ряд из нескольких файлов одновременно с R - PullRequest
0 голосов
/ 28 апреля 2020

Я получил много .csv файлов разных размеров. Я выбираю некоторые из них, которые соответствуют условию (те, которые соответствуют моему id в примере). Они упорядочены по дате и могут быть огромными. Мне нужно знать минимальную и максимальную даты этих файлов.

Я могу прочитать все, что хотел, и только для столбца date.hour, а затем легко найти минимальное и максимальное значения всех дат.

Но было бы намного быстрее, поскольку я повторяю это для тысячи идентификаторов, если бы я мог читать только первую и последнюю строки моих файлов.

Кто-нибудь получил представление о том, как решить эту проблему?

Этот код работает хорошо, но я хотел бы sh улучшить его.

функция чтения нескольких файлов одновременно

`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)`

Ответы [ 2 ]

0 голосов
/ 28 апреля 2020

Следующая функция прочитает первые две строки вашего 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)
}
0 голосов
/ 28 апреля 2020

В общем, read.table очень медленно. Если вы используете read_tsv, read_csv или read_delim из библиотеки readr, это будет уже намного, намного быстрее.

Если вы работаете в ОС Linux / Ma c, вы можете также читайте только первую или последнюю части, устанавливая канал, который будет более или менее мгновенным, независимо от размера файла. Предположим, у вас нет заголовков столбцов:

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)

Если вы хотите go на параллелизме, вы можете даже читать файлы параллельно, см., Например, library(parallel) и ?mclapply

...