你可能还会担心这种形式会创建数据的许多副本,占用大量内存。令人惊讶的是,事实并非如此。首先,请注意,主动担心内存问题并不是一种有效利用时间的方式:等到它真正成为问题(即内存耗尽)时再担心,而不是提前担心。其次,R 并不笨,它会在可能的情况下跨数据框共享列。让我们看一个实际的数据操作管道,其中我们向 ggplot2::diamonds 添加一个新列:
diamonds <- ggplot2::diamonds diamonds2 <- diamonds %>% dplyr::mutate(price_per_carat = price / carat) pryr::object_size(diamonds) #> 3.46 MB pryr::object_size(diamonds2) #> 3.89 MB pryr::object_size(diamonds, diamonds2) #> 3.89 MB
pryr::object_size() 给出其所有参数所占用的内存。这些结果乍一看似乎违反直觉:
- diamonds 占用 3.46 MB。
- diamonds2 占用 3.89 MB。
- diamonds 和 diamonds2 合起来只占用 3.89 MB!
这怎么可能呢?其实,diamonds2 与 diamonds 有 10 个共同的列:没有必要复制所有这些数据,所以这两个数据框共享一些变量。只有当你修改其中某个变量时,它才会被复制。在下面的例子中,我们修改了 diamonds$carat 中的一个值。这意味着 carat 变量不能再在两个数据框之间共享,必须进行复制。每个数据框的大小不变,但总大小增加了:
diamonds$carat[1] <- NA pryr::object_size(diamonds) #> 3.46 MB pryr::object_size(diamonds2) #> 3.89 MB pryr::object_size(diamonds, diamonds2) #> 4.32 MB