【问题标题】:Read files into R faster than while{rbind(read.table)}将文件读入 R 比 while{rbind(read.table)} 更快
【发布时间】:2020-01-01 19:26:25
【问题描述】:

我正在将一些每日 Apache 日志文件读入 R。这些文件都被命名为“logfile_”加上它们的日期,例如logfile_2019-12-30。以下是我阅读文件的方式:

path <- "/path/to/logs/"

beginning <- as.Date("2019-12-01", format="%Y-%m-%d")
ending <- as.Date("2019-12-31", format="%Y-%m-%d")

d <- beginning
dat <- data.frame()
while (d < ending)
{
    dat <- rbind(dat, read.table(paste0(path, "logfile_", d), stringsAsFactors = FALSE))
    d <- d + 1                    
}

在一个月内(大约有一百万行日志条目)while-loop 大约需要四分钟来执行。我想阅读和处理几年的文件,但不想等待几个小时。

如何才能更高效、更快地读取文件?

【问题讨论】:

    标签: r while-loop rbind read.table


    【解决方案1】:

    使用data.table::rbindlistfread 应该更快

    library(data.table)
    beginning <- as.Date("2019-12-01")
    ending <- as.Date("2019-12-31")
    
    out <- rbindlist(lapply(paste0(path, "logfile_", 
                     seq(beginning, ending, by = "1 day")), fread))
    

    或者你也可以使用dplyr::bind_rows

    out <- dplyr::bind_rows(lapply(paste0(path, "logfile_", 
          seq(beginning, ending, by = "1 day")), read.table, stringsAsFactors = FALSE))
    

    【讨论】:

    • 如果您打算将data.table 带入其中(这是一件好事),请尝试使用fread 进行超快速的 CSV 文件输入。
    • data.table() 似乎发现阅读 Apache 日志文件很困难。您的第一个示例返回一个错误:Error in rbindlist(...): Item 58 has 3 columns, inconsistent with item 1 which has 12 columns. To fill missing columns use fill=TRUE. In addition: There were 50 or more warnings (use warnings() to see the first 50) &gt; warnings() Warning messages: 1: In FUN(X[[i]], ...) : Found and resolved improper quoting out-of-sample. First healed line 2419: ... 我知道它来自请求的 URL 或引用中的字符。 read.table() 处理得很好。
    • @fluctuatingpsychosis 也许fread 需要一些额外的参数。您可以使用第二个选项或使用out &lt;- data.table::rbindlist(lapply(paste0(path, "logfile_", seq(beginning, ending, by = "1 day")), read.table, stringsAsFactors = FALSE))read.table
    • 您的第二个示例使用 dplyr,我的示例需要 11 秒。那很好。谢谢。
    • 使用我的示例,您的第一个示例需要 9 秒。由于代表人数少,我无法投票,但我会接受这个答案。再次感谢您。
    【解决方案2】:

    您可以通过使用序列函数来创建日期向量,然后在 read.table 中使用该向量,如下所示;

    path <- "/path/to/logs/"
    
    beginning <- as.Date("2019-12-01", format="%Y-%m-%d")
    ending <- as.Date("2019-12-31", format="%Y-%m-%d")
    
    file_names <- paste0(path, "logfile_", seq(beginning, ending ,by = 1))
    do.call(rbind, lapply(file_names, read.table, stringsAsFactors = FALSE))
    

    【讨论】:

    • lapply(file_names, stringsAsFactors = FALSE) 缺少一些重要部分。
    • 你的意思是缺少函数参数吗?通常它取决于问题中文件的格式,只有 stringsAsFactors 缺失。我还添加了 sep 这些通常是主要的,但通常取决于文件。
    • 你得到了lapply 的文件名和stringsAsFactors,但没有适用于列表的函数。你的意思是lapply(file_names, read.table, stringsAsFactors=FALSE)?编写的代码不可能工作。
    • 使用我的示例,您的解决方案在 16 秒内完成,这是一个巨大的改进。谢谢你。不幸的是,由于代表人数少,我无法投票。
    猜你喜欢
    • 1970-01-01
    • 2015-12-12
    • 2017-10-17
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 2010-11-27
    相关资源
    最近更新 更多