包环境在管道中未按预期工作
Package environments are not working as expected in a pipeline
在我正在处理的包中,我使用环境来保存和检索数据框的标签。
在 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
}
这完全符合预期,因为 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)
由 reprex package (v0.3.0)
于 2021-01-26 创建
但是,save_labels(mtcars2)
returns 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
由 reprex package (v0.3.0)
于 2021-01-26 创建
确实,当我们使用管道时,当我们到达import_labels()
时,环境变量还没有设置。如果我重新 运行 这段代码,它不会抛出任何错误,但这会产生误导,因为它会引用 labels_env$last_save
.
的先前值
我对管道的理解不够好,无法使它正常工作。此外,它似乎特定于包环境,因为我无法在普通 R 脚本中重现此行为。
有没有一种方法可以在包中使用带有这种环境变量的管道?
这实际上是由于软件包 magrittr
(提供管道)从 v1.5 升级到 v2.0 时发生的重大更改造成的。
这已在 the blog and on NEWS.md 上进行了解释。
可以在 this GitHub issue.
上找到更具体的可重现示例
在新的 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
}
在我正在处理的包中,我使用环境来保存和检索数据框的标签。
在 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
}
这完全符合预期,因为 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)
由 reprex package (v0.3.0)
于 2021-01-26 创建但是,save_labels(mtcars2)
returns 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
由 reprex package (v0.3.0)
于 2021-01-26 创建确实,当我们使用管道时,当我们到达import_labels()
时,环境变量还没有设置。如果我重新 运行 这段代码,它不会抛出任何错误,但这会产生误导,因为它会引用 labels_env$last_save
.
我对管道的理解不够好,无法使它正常工作。此外,它似乎特定于包环境,因为我无法在普通 R 脚本中重现此行为。
有没有一种方法可以在包中使用带有这种环境变量的管道?
这实际上是由于软件包 magrittr
(提供管道)从 v1.5 升级到 v2.0 时发生的重大更改造成的。
这已在 the blog and on NEWS.md 上进行了解释。
可以在 this GitHub issue.
上找到更具体的可重现示例在新的 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
}