rsample::bootstraps 是否存储数据而不仅仅是行索引?

Does rsample::bootstraps store data rather than just row indices?

我试图理解为什么 rsample::bootstraps 函数显然为每个 bootstrap 样本存储了整个数据集。我原以为该函数只会存储一次数据集,以及每个重新采样的 bootstrap 索引。在下面你可以看到基本结构,每次重采样都会重复:

> set.seed(1)
> test <- rsample::bootstraps(mtcars[, 1:3], times = 2)
> str(test)
bootstraps [2 × 2] (S3: bootstraps/rset/tbl_df/tbl/data.frame)
 $ splits:List of 2
  ..$ :List of 4
  .. ..$ data  :'data.frame':   32 obs. of  3 variables:
  .. .. ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
  .. .. ..$ cyl : num [1:32] 6 6 4 6 8 6 8 4 4 6 ...
  .. .. ..$ disp: num [1:32] 160 160 108 258 360 ...
  .. ..$ in_id : int [1:32] 25 4 7 1 2 29 23 11 14 18 ...
  .. ..$ out_id: logi NA
  .. ..$ id    : tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
  .. .. ..$ id: chr "Bootstrap1"
  .. ..- attr(*, "class")= chr [1:2] "rsplit" "boot_split"
  ..$ :List of 4
  .. ..$ data  :'data.frame':   32 obs. of  3 variables:
  .. .. ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
  .. .. ..$ cyl : num [1:32] 6 6 4 6 8 6 8 4 4 6 ...
  .. .. ..$ disp: num [1:32] 160 160 108 258 360 ...
  .. ..$ in_id : int [1:32] 25 12 15 1 20 3 6 10 10 6 ...
  .. ..$ out_id: logi NA
  .. ..$ id    : tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
  .. .. ..$ id: chr "Bootstrap2"
  .. ..- attr(*, "class")= chr [1:2] "rsplit" "boot_split"
 $ id    : chr [1:2] "Bootstrap1" "Bootstrap2"
 - attr(*, "times")= num 2
 - attr(*, "apparent")= logi FALSE
 - attr(*, "strata")= logi FALSEbootstraps [1 × 2] (S3: 

$data 项目似乎重复进行了额外的重新采样,并且变化的重新采样索引存储在 in_id 中。明显的成本是对象的大小与数据大小乘以重采样次数成比例增长。来自 object.size(test) 的单个重采样的大小为 7800 字节。对于 200 次重采样,它是 1236824 字节。

每次重采样的数据都不会重复;你可以see an example of this in the README for the rsample package。原始数据没有被修改; R 不复制。

每次重采样都有一些 RAM 开销,mtcars 有点小,无法很好地理解这一点,所以让我们看看更大的数据集,例如 Ames住房数据集(查看 README 中的不同示例):

library(rsample)
library(lobstr)
data(ames, package = "modeldata")

obj_size(ames)
#> 1,042,736 B

set.seed(123)
boots <- bootstraps(ames, times = 50)
obj_size(boots)
#> 1,670,760 B

## what is the object size per resample?
obj_size(boots)/nrow(boots)
#> 33,415.2 B

## what is the relative size of the bootstrap object compared to the original?
as.numeric(obj_size(boots)/obj_size(ames))
#> [1] 1.602285

reprex package (v1.0.0)

于 2021-02-17 创建

比 50 少很多! bootstrap 对象的内存比原始数据集大不到 50 倍。

注意我使用了 lobstr to compare the sizes instead of object.size(). The reason is because object.size() does not entirely include the size of all environments in objects and is less accurate overall。如果您曾经尝试使用 object.size() 测量 R 中对象的 RAM,并且对为什么它与您的 OS 所说的不匹配感到困惑,这可能就是原因。使用lobstr::obj_size()可以解决这个问题。