dplyr滞后调用中的意外整齐评估行为

时间:2018-07-18 00:19:38

标签: r dplyr tidyeval

我有一个需要一个数据框和几个变量的函数,我希望它使用整洁的评估原理来产生一组滞后变量。它以简单的形式看起来像这样:

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.

2 个答案:

答案 0 :(得分:4)

您正在混淆准引用语法。要么

  • 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
    
  • 或为var1var2提供未加引号的表达式,并用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
    

答案 1 :(得分:1)

我们可以创建一个可以使用未加引号和加引号的字符串的函数

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