dplyr 滞后调用中意外的整洁评估行为
Unexpected tidy eval behaviour in dplyr lag call
我有一个函数,它接受一个数据框和几个变量,我希望它使用整洁的评估原则生成一组滞后变量。在它的简单形式中,它看起来像这样:
library(dplyr)
cor_lags <- function(df, var1, var2) {
var1 <- enquo(var1)
var2 <- enquo(var2)
df %>%
select(!!var1, !!var2) %>%
mutate(lag1 = lag(!!var2, 1),
lag2 = lag(!!var2, 2),
lag3 = lag(!!var2, 3),
lag4 = lag(!!var2, 4),
lag5 = lag(!!var2, 5),
lag6 = lag(!!var2, 6))
}
但是,这会为所有滞后变量生成 NA
值。
cor_lags(dts_wide,"P26","P1")
# A tibble: 24 x 8
P26 P1 lag1 lag2 lag3 lag4 lag5 lag6
<dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 84332. 2258. NA NA NA NA NA NA
2 63995. 2752. NA NA NA NA NA NA
3 86208. 10126. NA NA NA NA NA NA
4 103455. 3767. NA NA NA NA NA NA
5 160524. 12986. NA NA NA NA NA NA
6 306683. 3944. NA NA NA NA NA NA
7 599589. 3695. NA NA NA NA NA NA
8 642343. 6202. NA NA NA NA NA NA
9 482021. 8769. NA NA NA NA NA NA
10 220949. 5059. NA NA NA NA NA NA
有没有理由!!评估人员不在 lag
通话中工作?他们显然在 select
通话中工作。
上述调用的预期行为在实践中应该像这段代码一样有效(有效):
# Expected
cor_lags <- function(df, var1, var2) {
var1 <- enquo(var1)
var2 <- enquo(var2)
df %>%
select(!!var1, !!var2) %>%
mutate(lag1 = lag(P1, 1),
lag2 = lag(P1, 2),
lag3 = lag(P1, 3),
lag4 = lag(P1, 4),
lag5 = lag(P1, 5),
lag6 = lag(P1, 6))
}
并且如预期的那样产生:
cor_lags(dts_wide,"P26","P1")
# A tibble: 24 x 8
P26 P1 lag1 lag2 lag3 lag4 lag5 lag6
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 84332. 2258. NA NA NA NA NA NA
2 63995. 2752. 2258. NA NA NA NA NA
3 86208. 10126. 2752. 2258. NA NA NA NA
4 103455. 3767. 10126. 2752. 2258. NA NA NA
5 160524. 12986. 3767. 10126. 2752. 2258. NA NA
6 306683. 3944. 12986. 3767. 10126. 2752. 2258. NA
7 599589. 3695. 3944. 12986. 3767. 10126. 2752. 2258.
8 642343. 6202. 3695. 3944. 12986. 3767. 10126. 2752.
9 482021. 8769. 6202. 3695. 3944. 12986. 3767. 10126.
10 220949. 5059. 8769. 6202. 3695. 3944. 12986. 3767.
您混淆了准引号语法。要么
将enquo
替换为sym
(或rlang::sym
)将字符串变成符号,
cor_lags <- function(df, var1, var2) {
var1 <- sym(var1); # Turn string into symbol
var2 <- sym(var2); # Turn string into symbol
df %>%
select(!!var1, !!var2) %>%
mutate(lag1 = lag(!!var2, 1),
lag2 = lag(!!var2, 2),
lag3 = lag(!!var2, 3),
lag4 = lag(!!var2, 4),
lag5 = lag(!!var2, 5),
lag6 = lag(!!var2, 6))
}
cor_lags(mtcars, "mpg", "disp") %>% head() # var1, var2 as string
# mpg disp lag1 lag2 lag3 lag4 lag5 lag6
#1 21.0 160 NA NA NA NA NA NA
#2 21.0 160 160 NA NA NA NA NA
#3 22.8 108 160 160 NA NA NA NA
#4 21.4 258 108 160 160 NA NA NA
#5 18.7 360 258 108 160 160 NA NA
#6 18.1 225 360 258 108 160 160 NA
或为 var1
和 var2
提供不带引号的表达式,并用 enquo
将它们转换为 quosures
cor_lags <- function(df, var1, var2) {
var1 <- enquo(var1) # Turn expression into quosure
var2 <- enquo(var2) # Turn expression into quosure
df %>%
select(!!var1, !!var2) %>%
mutate(lag1 = lag(!!var2, 1),
lag2 = lag(!!var2, 2),
lag3 = lag(!!var2, 3),
lag4 = lag(!!var2, 4),
lag5 = lag(!!var2, 5),
lag6 = lag(!!var2, 6))
}
cor_lags(mtcars, mpg, disp) %>% head() # var1, var2 as expressions
# mpg disp lag1 lag2 lag3 lag4 lag5 lag6
#1 21.0 160 NA NA NA NA NA NA
#2 21.0 160 160 NA NA NA NA NA
#3 22.8 108 160 160 NA NA NA NA
#4 21.4 258 108 160 160 NA NA NA
#5 18.7 360 258 108 160 160 NA NA
#6 18.1 225 360 258 108 160 160 NA
我们可以创建一个函数,它可以接受不带引号和带引号的字符串
library(tidyverse)
library(rlang)
cor_lags <- function(df, var1, var2) {
var1 <- parse_expr(quo_name(enquo(var1)))
var2 <- parse_expr(quo_name(enquo(var2)))
df %>%
select(!! var1, !! var2) %>%
mutate(lag1 = lag(!!var2, 1),
lag2 = lag(!!var2, 2),
lag3 = lag(!!var2, 3),
lag4 = lag(!!var2, 4),
lag5 = lag(!!var2, 5),
lag6 = lag(!!var2, 6))
}
-测试
cor_lags(mtcars, "mpg", "disp") %>%
head()
# mpg disp lag1 lag2 lag3 lag4 lag5 lag6
#1 21.0 160 NA NA NA NA NA NA
#2 21.0 160 160 NA NA NA NA NA
#3 22.8 108 160 160 NA NA NA NA
#4 21.4 258 108 160 160 NA NA NA
#5 18.7 360 258 108 160 160 NA NA
#6 18.1 225 360 258 108 160 160 NA
cor_lags(mtcars, mpg, disp) %>%
head()
# mpg disp lag1 lag2 lag3 lag4 lag5 lag6
#1 21.0 160 NA NA NA NA NA NA
#2 21.0 160 160 NA NA NA NA NA
#3 22.8 108 160 160 NA NA NA NA
#4 21.4 258 108 160 160 NA NA NA
#5 18.7 360 258 108 160 160 NA NA
#6 18.1 225 360 258 108 160 160 NA
我有一个函数,它接受一个数据框和几个变量,我希望它使用整洁的评估原则生成一组滞后变量。在它的简单形式中,它看起来像这样:
library(dplyr)
cor_lags <- function(df, var1, var2) {
var1 <- enquo(var1)
var2 <- enquo(var2)
df %>%
select(!!var1, !!var2) %>%
mutate(lag1 = lag(!!var2, 1),
lag2 = lag(!!var2, 2),
lag3 = lag(!!var2, 3),
lag4 = lag(!!var2, 4),
lag5 = lag(!!var2, 5),
lag6 = lag(!!var2, 6))
}
但是,这会为所有滞后变量生成 NA
值。
cor_lags(dts_wide,"P26","P1")
# A tibble: 24 x 8
P26 P1 lag1 lag2 lag3 lag4 lag5 lag6
<dbl> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
1 84332. 2258. NA NA NA NA NA NA
2 63995. 2752. NA NA NA NA NA NA
3 86208. 10126. NA NA NA NA NA NA
4 103455. 3767. NA NA NA NA NA NA
5 160524. 12986. NA NA NA NA NA NA
6 306683. 3944. NA NA NA NA NA NA
7 599589. 3695. NA NA NA NA NA NA
8 642343. 6202. NA NA NA NA NA NA
9 482021. 8769. NA NA NA NA NA NA
10 220949. 5059. NA NA NA NA NA NA
有没有理由!!评估人员不在 lag
通话中工作?他们显然在 select
通话中工作。
上述调用的预期行为在实践中应该像这段代码一样有效(有效):
# Expected
cor_lags <- function(df, var1, var2) {
var1 <- enquo(var1)
var2 <- enquo(var2)
df %>%
select(!!var1, !!var2) %>%
mutate(lag1 = lag(P1, 1),
lag2 = lag(P1, 2),
lag3 = lag(P1, 3),
lag4 = lag(P1, 4),
lag5 = lag(P1, 5),
lag6 = lag(P1, 6))
}
并且如预期的那样产生:
cor_lags(dts_wide,"P26","P1")
# A tibble: 24 x 8
P26 P1 lag1 lag2 lag3 lag4 lag5 lag6
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 84332. 2258. NA NA NA NA NA NA
2 63995. 2752. 2258. NA NA NA NA NA
3 86208. 10126. 2752. 2258. NA NA NA NA
4 103455. 3767. 10126. 2752. 2258. NA NA NA
5 160524. 12986. 3767. 10126. 2752. 2258. NA NA
6 306683. 3944. 12986. 3767. 10126. 2752. 2258. NA
7 599589. 3695. 3944. 12986. 3767. 10126. 2752. 2258.
8 642343. 6202. 3695. 3944. 12986. 3767. 10126. 2752.
9 482021. 8769. 6202. 3695. 3944. 12986. 3767. 10126.
10 220949. 5059. 8769. 6202. 3695. 3944. 12986. 3767.
您混淆了准引号语法。要么
将
enquo
替换为sym
(或rlang::sym
)将字符串变成符号,cor_lags <- function(df, var1, var2) { var1 <- sym(var1); # Turn string into symbol var2 <- sym(var2); # Turn string into symbol df %>% select(!!var1, !!var2) %>% mutate(lag1 = lag(!!var2, 1), lag2 = lag(!!var2, 2), lag3 = lag(!!var2, 3), lag4 = lag(!!var2, 4), lag5 = lag(!!var2, 5), lag6 = lag(!!var2, 6)) } cor_lags(mtcars, "mpg", "disp") %>% head() # var1, var2 as string # mpg disp lag1 lag2 lag3 lag4 lag5 lag6 #1 21.0 160 NA NA NA NA NA NA #2 21.0 160 160 NA NA NA NA NA #3 22.8 108 160 160 NA NA NA NA #4 21.4 258 108 160 160 NA NA NA #5 18.7 360 258 108 160 160 NA NA #6 18.1 225 360 258 108 160 160 NA
或为
将它们转换为 quosuresvar1
和var2
提供不带引号的表达式,并用enquo
cor_lags <- function(df, var1, var2) { var1 <- enquo(var1) # Turn expression into quosure var2 <- enquo(var2) # Turn expression into quosure df %>% select(!!var1, !!var2) %>% mutate(lag1 = lag(!!var2, 1), lag2 = lag(!!var2, 2), lag3 = lag(!!var2, 3), lag4 = lag(!!var2, 4), lag5 = lag(!!var2, 5), lag6 = lag(!!var2, 6)) } cor_lags(mtcars, mpg, disp) %>% head() # var1, var2 as expressions # mpg disp lag1 lag2 lag3 lag4 lag5 lag6 #1 21.0 160 NA NA NA NA NA NA #2 21.0 160 160 NA NA NA NA NA #3 22.8 108 160 160 NA NA NA NA #4 21.4 258 108 160 160 NA NA NA #5 18.7 360 258 108 160 160 NA NA #6 18.1 225 360 258 108 160 160 NA
我们可以创建一个函数,它可以接受不带引号和带引号的字符串
library(tidyverse)
library(rlang)
cor_lags <- function(df, var1, var2) {
var1 <- parse_expr(quo_name(enquo(var1)))
var2 <- parse_expr(quo_name(enquo(var2)))
df %>%
select(!! var1, !! var2) %>%
mutate(lag1 = lag(!!var2, 1),
lag2 = lag(!!var2, 2),
lag3 = lag(!!var2, 3),
lag4 = lag(!!var2, 4),
lag5 = lag(!!var2, 5),
lag6 = lag(!!var2, 6))
}
-测试
cor_lags(mtcars, "mpg", "disp") %>%
head()
# mpg disp lag1 lag2 lag3 lag4 lag5 lag6
#1 21.0 160 NA NA NA NA NA NA
#2 21.0 160 160 NA NA NA NA NA
#3 22.8 108 160 160 NA NA NA NA
#4 21.4 258 108 160 160 NA NA NA
#5 18.7 360 258 108 160 160 NA NA
#6 18.1 225 360 258 108 160 160 NA
cor_lags(mtcars, mpg, disp) %>%
head()
# mpg disp lag1 lag2 lag3 lag4 lag5 lag6
#1 21.0 160 NA NA NA NA NA NA
#2 21.0 160 160 NA NA NA NA NA
#3 22.8 108 160 160 NA NA NA NA
#4 21.4 258 108 160 160 NA NA NA
#5 18.7 360 258 108 160 160 NA NA
#6 18.1 225 360 258 108 160 160 NA