r-为什么read_csv的结果比read.csv的结果大

  • 本文关键字:结果 csv read r csv readr
  • 更新时间 :
  • 英文 :


我在一个项目中导入了许多(>300(.csv文件,我偶然发现了一个非常奇怪的事情。

当比较read_csvread.csv的结果时,在大小上存在显著差异。Windows列出的所有文件的文件大小为~442 MB。

使用readr

library(tidyverse)
datadir <- "Z:\data\attachments"
list_of_files <- list.files(path = datadir, full.names = TRUE)
readr_data <- lapply(list_of_files, function(x) {
read_csv(x, col_types = cols())
})
object.size(readr_data)
#> 416698080 bytes
str(readr_data[1])
#> List of 1
#>  $ : tibble [2,123 x 80] (S3: spec_tbl_df/tbl_df/tbl/data.frame)

使用base方法

base_data <- lapply(list_of_files, function(x) {
read.csv(x)
})

object.size(base_data)
#> 393094616 bytes
str(base_data[1])
#> List of 1
#>  $ :'data.frame':    2123 obs. of  80 variables:
# Compare size
object.size(readr_data) / object.size(base_data) * 100
#> 106 bytes

现在6%可能没有那么多,但仍然是23MB,我仍然感兴趣的是为什么这些不同。此外,这两个都比Windows报告的要小。

为什么列表大小不同,这重要吗?

编辑:显然有些课程是不同的。我用了这个方法:

readr_class <- sapply(readr_data[[1]], class)
base_class <- sapply(base_data[[1]], class)
result <- data.frame(readr_class, base_class)

这些就是区别:

readr_class base_class
var1              numeric    integer
var2              numeric    integer
var3              numeric    integer
var4              character  integer

选择正确的函数对于编写高效的代码当然非常重要。不同函数和包中的优化程度将影响对象的存储方式、大小以及在其上运行的操作速度。请考虑以下内容。

library(data.table)
a <- c(1:1000000)
b <- rnorm(1000000)
mat <- as.matrix(cbind(a, b))
df <- data.frame(a, b)
dt <- data.table::as.data.table(mat)
cat(paste0("Matrix size: ",object.size(mat), "ndf size: ", object.size(df), " (",round(object.size(df)/object.size(mat),2) ,")ndt size: ", object.size(dt), " (",round(object.size(dt)/object.size(mat),2),")" ))
Matrix size: 16000568
df size: 12000848 (0.75)
dt size: 4001152 (0.25)

因此,在这里您已经看到data.table存储相同的数据所使用的空间是旧matrix的4倍,是data.frame的3倍。现在关于操作速度:

> microbenchmark(df[df$a*df$b>500,], mat[mat[,1]*mat[,2]>500,], dt[a*b>500])
Unit: milliseconds
expr       min        lq     mean   median        uq      max neval
df[df$a * df$b > 500, ] 23.766201 24.136201 26.49715 24.34380 30.243300  32.7245   100
mat[mat[, 1] * mat[, 2] > 500, ] 13.010000 13.146301 17.18246 13.41555 20.105450 117.9497   100
dt[a * b > 500]  8.502102  8.644001 10.90873  8.72690  8.879352 112.7840   100

data.tabledata.frame上比base快1.7倍,比使用matrix快2.5倍。

这还不是全部,对于几乎任何CSV导入,使用data.table::fread都会改变你的生活。尝试一下,不要使用read.csvread_csv

IMHOdata.table没有得到应有的一半的喜爱,它是性能最好的全方位软件包,语法非常简洁。下面的小插曲应该会让你很快走上正轨,相信我,这是值得的

为了进一步提高性能,Rfast包含许多流行功能和问题的Rcpp实现,例如rowSort()


EDIT:fread的速度是由于在C代码级别进行的优化,包括使用指针进行内存映射,以及强制现用技术,坦率地说,我无法解释这些技术。这篇文章包含了作者Matt Dowle的一些解释,以及他与dplyr的作者Hadley Wickham之间的一段有趣的(如果简短的话(讨论。

最新更新