read.csv 比 data.table::fread 快

read.csv faster than data.table::fread

我在网上看到我应该使用 data.table 和 fread 来加载我的数据。

但是当我运行一个基准时,我得到以下结果

Unit: milliseconds
expr       min        lq      mean    median        uq        max neval
test1  1.229782  1.280000  1.382249  1.366277  1.460483   1.580176    10
test3  1.294726  1.355139  1.765871  1.391576  1.542041   4.770357    10
test2 23.115503 23.345451 42.307979 25.492186 57.772522 125.941734    10

代码见下方

loadpath <- readRDS("paths.rds")

microbenchmark(
  test1 = read.csv(paste0(loadpath,"data.csv"),header=TRUE,sep=";", stringsAsFactors = FALSE,colClasses = "character"),
  test2 = data.table::fread(paste0(loadpath,"data.csv"), sep=";"),
  test3 = read.csv(paste0(loadpath,"data.csv")),
  times = 10
) %>%
  print(order = "min") 

我知道 fread() 应该比 read.csv() 快,因为它尝试首先将行作为字符读入内存,然后尝试将它们转换为整数和因子作为数据类型。另一方面,fread() 只是将所有内容都读取为字符。

如果这是真的,test2 不应该比 test3 快吗?

有人能给我解释一下,为什么我使用 test2test1 没有达到加速或至少相同的速度? :)

如果查看函数,您会发现 fread 比 read.csv 执行更多检查。如果您正在阅读的文件很小,我会花更多的时间来检查和准备阅读,而不是实际阅读。

data.table 对于大型数据集来说速度快得令人难以置信。

如果您考虑更大的文件,

data.table::fread 的显着性能优势就会变得很明显。这是一个完全可重现的例子。

  1. 让我们生成一个包含 10^5 行和 100 列的 CSV 文件

    if (!file.exists("test.csv")) {
        set.seed(2017)
        df <- as.data.frame(matrix(runif(10^5 * 100), nrow = 10^5))
        write.csv(df, "test.csv", quote = F)
    }
    
  2. 我们 运行 进行了 microbenchmark 分析(请注意,这可能需要几分钟,具体取决于您的硬件)

    library(microbenchmark)
    res <- microbenchmark(
        read.csv = read.csv("test.csv", header = TRUE, stringsAsFactors = FALSE, colClasses = "numeric"),
        fread = data.table::fread("test.csv", sep = ",", stringsAsFactors = FALSE, colClasses = "numeric"),
        times = 10)
    res
    #          Unit: milliseconds
    #     expr        min         lq       mean     median         uq        max
    # read.csv 17034.2886 17669.8653 19369.1286 18537.7057 20433.4933 23459.4308
    #    fread   287.1108   311.6304   432.8106   356.6992   460.6167   888.6531
    
    
    library(ggplot2)
    autoplot(res)