为什么read_csv的结果比read.csv的结果大?
Why are the results of read_csv larger than those of read.csv?
我在项目中导入许多(> 300).csv 文件,我偶然发现了一个非常奇怪的事件。
比较 read_csv
和 read.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% 可能不是那么多,但仍然是 23 MB,我仍然想知道为什么它们不同。此外,这两个值都小于 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
存储相同数据所用的 space 比旧 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.table
的过滤速度比 data.frame
上的 base
快 1.7 倍,比使用 matrix
.
快 2.5 倍
这还不是全部,对于几乎所有 CSV 导入,使用 data.table::fread
都会改变您的生活。试一试 read.csv
或 read_csv
.
恕我直言 data.table
没有得到应有的一半爱,最好的 all-round 性能包和非常简洁的语法。 following vignettes 应该会让您快速上路,相信我,这是值得的。
为了进一步提高性能 Rfast
包含许多 Rcpp
流行函数和问题的实现,例如 rowSort()
。
编辑:fread
的速度是由于在 C-code 级别进行的优化,涉及使用内存映射指针和 coerce-as-you-go 技术,坦率地说,这超出了我的知识范围解释。 This post 包含作者 Matt Dowle 的一些解释,以及他与 dplyr
的作者 Hadley Wickham 之间的一段有趣但简短的讨论。
我在项目中导入许多(> 300).csv 文件,我偶然发现了一个非常奇怪的事件。
比较 read_csv
和 read.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% 可能不是那么多,但仍然是 23 MB,我仍然想知道为什么它们不同。此外,这两个值都小于 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
存储相同数据所用的 space 比旧 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.table
的过滤速度比 data.frame
上的 base
快 1.7 倍,比使用 matrix
.
这还不是全部,对于几乎所有 CSV 导入,使用 data.table::fread
都会改变您的生活。试一试 read.csv
或 read_csv
.
恕我直言 data.table
没有得到应有的一半爱,最好的 all-round 性能包和非常简洁的语法。 following vignettes 应该会让您快速上路,相信我,这是值得的。
为了进一步提高性能 Rfast
包含许多 Rcpp
流行函数和问题的实现,例如 rowSort()
。
编辑:fread
的速度是由于在 C-code 级别进行的优化,涉及使用内存映射指针和 coerce-as-you-go 技术,坦率地说,这超出了我的知识范围解释。 This post 包含作者 Matt Dowle 的一些解释,以及他与 dplyr
的作者 Hadley Wickham 之间的一段有趣但简短的讨论。