Почему `object.size` окружения меньше, чем` object.size` объектов в окружении? - PullRequest
2 голосов
/ 30 апреля 2019

Я столкнулся с непонятной ситуацией при написании фабрики функций. У меня есть столбец со столбцами идентифицирующей информации и столбец списка, содержащий данные.

tib <-
    tibble(
        id_1 = letters[1:3],
        id_2 = LETTERS[1:3],
        data = list(mtcars, iris, volcano)
    )

Я создал фабрику функций, чтобы упростить получение наборов данных, хранящихся в этой таблице.

data_getter <- function(data) {
    force(data)
    function(id_1, id_2) {
        where <- data$id_1 == id_1 & data$id_2 == id_2
        data[where, ]$data %>% 
            purrr::flatten_df()
    }
}

get_from_tib <- data_getter(tib)

На самом деле, фрейм данных, с которым я работаю, очень большой. Насколько я понимаю, get_from_tib охватывает среду, которая включает tib. Когда я это сделал, я волновался, что при дублировании этого большого набора данных у меня начнется нехватка памяти. Однако я был очень удивлен, когда object.size моей функции было меньше, чем набор данных, который предположительно захвачен им!

object.size(tib)
21752 bytes

object.size(get_from_tib)
8416 bytes

Это работает, даже если я удаляю tib из рабочей среды

rm(tib)

object.size(get_from_tib)
8416 bytes

Почему окружающая среда намного меньше? object.size - просто неправильная функция для получения размера всех объектов, содержащихся в среде?

Ниже представлены

library(magrittr)

tib <-
    dplyr::tibble(
        id_1 = letters[1:3],
        id_2 = LETTERS[1:3],
        data = list(mtcars, iris, USArrests)
    )


data_getter <- function(data) {
    force(data)
    function(id_1, id_2) {
        where <- data$id_1 == id_1 & data$id_2 == id_2
        data[where, ]$data %>% 
            purrr::flatten_df()
    }
}

get_from_tib <- data_getter(tib)

get_from_tib('c', 'C')
#> # A tibble: 50 x 4
#>    Murder Assault UrbanPop  Rape
#>     <dbl>   <int>    <int> <dbl>
#>  1   13.2     236       58  21.2
#>  2   10       263       48  44.5
#>  3    8.1     294       80  31  
#>  4    8.8     190       50  19.5
#>  5    9       276       91  40.6
#>  6    7.9     204       78  38.7
#>  7    3.3     110       77  11.1
#>  8    5.9     238       72  15.8
#>  9   15.4     335       80  31.9
#> 10   17.4     211       60  25.8
#> # … with 40 more rows


object.size(tib)
#> 21752 bytes
object.size(get_from_tib)
#> 8416 bytes


rm(tib)
object.size(get_from_tib)
#> 8416 bytes

Создано в 2019-04-30 пакетом Представить (v0.2.1)

1 Ответ

3 голосов
/ 30 апреля 2019

Это связано с частью на странице справки ?object.size, которая сообщает

Связанное пространство (например, среда функции и то, на что указывает указатель в EXTPTRSXP) не являетсявключается в расчет.

Переменная data фиксируется в замыкании;на самом деле это не «в» код функции, который возвращается из data_getter.

Функция pyry::object_size() лучше справляется с учетом окружающей среды.

pryr::object_size(tib)
# 21 kB
pryr::object_size(get_from_tib)
# 26.9 kB
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...