#r #environment-variables #pipe
#r #переменные среды #труба
Вопрос:
В пакете, над которым я работаю, я использую среды для сохранения и извлечения меток фрейма данных.
В magrittr
конвейере я хочу сохранить их в переменной среды, которую я получу позже.
Однако я сталкиваюсь с проблемой: кажется, что переменные среды не были изменены до конца конвейера.
Вот пример с большинством полезных функций:
devtools::install_github("DanChaltiel/crosstable", build_vignettes=TRUE)
library(crosstable) #for functions set_label() and get_label() but you can test
#with other label-management packages (Hmisc, expss...)
labels_env = rlang::new_environment()
save_labels = function(.tbl){
labels_env$last_save = tibble(
name=names(.tbl),
label=get_label(.tbl)[.data$name]
)
invisible(.tbl)
}
get_last_save = function(){
labels_env$last_save
}
import_labels = function(.tbl){
data_label = get_last_save()
for(i in 1:nrow(data_label)){
name = as.character(data_label[i, name_from])
label = as.character(data_label[i, label_from])
.tbl[name] = set_label(.tbl[name], label)
}
.tbl
}
Это работает точно так, как задумано, поскольку label for disp
будет NULL
в противном случае:
library(dplyr)
library(crosstable)
save_labels(mtcars2)
mtcars2 %>%
transmute(disp=as.numeric(disp) 1) %>% #removes the label attribute of disp
import_labels() %>% #
crosstable(disp)
#> .id label variable value
#> 1 disp Displacement (cu.in.) Min / Max 72.1 / 473.0
#> 2 disp Displacement (cu.in.) Med [IQR] 197.3 [121.8;327.0]
#> 3 disp Displacement (cu.in.) Mean (std) 231.7 (123.9)
#> 4 disp Displacement (cu.in.) N (NA) 32 (0)
Создано 2021-01-26 пакетом reprex (версия 0.3.0)
Однако save_labels(mtcars2)
возвращает mtcars2
невидимо, поэтому я хотел бы иметь возможность передавать всю последовательность. К сожалению, это выдает ошибку:
library(dplyr)
library(crosstable)
mtcars2 %>%
save_labels() %>%
transmute(disp=as.numeric(disp) 1) %>%
import_labels() %>% #
crosstable(disp)
#> Error in .subset2(x, i, exact = exact): attempt to select less than one element in get1index
Создано 2021-01-26 пакетом reprex (версия 0.3.0)
Действительно, при использовании каналов переменная среды еще не установлена, когда мы добираемся до import_labels()
. Если я повторно запущу этот код, он не выдаст никакой ошибки, но это будет вводить в заблуждение, поскольку будет ссылаться на предыдущее значение labels_env$last_save
.
Мое понимание каналов недостаточно хорошо, чтобы заставить это работать. Более того, похоже, что это специфично для среды пакета, поскольку я не смог воспроизвести это поведение в простом R-скрипте.
Есть ли способ, которым я могу использовать каналы с такой переменной окружения внутри пакета?
Ответ №1:
На самом деле это было вызвано критическим изменением, когда пакет magrittr
(который предоставляет каналы) перешел с версии v1.5 на версию v2.0.
Это было объяснено в блоге и на NEWS.md .
Более конкретный воспроизводимый пример можно найти в этом выпуске GitHub.
В новой magrittr
версии последовательность вычислений изменилась, поэтому, чтобы побочные эффекты происходили в правильном порядке, вам необходимо выполнить принудительную оценку:
import_labels = function(.tbl){
force(.tbl) #force evaluation
data_label = get_last_save()
for(i in 1:nrow(data_label)){
name = as.character(data_label[i, name_from])
label = as.character(data_label[i, label_from])
.tbl[name] = set_label(.tbl[name], label)
}
.tbl
}