代码之家  ›  专栏  ›  技术社区  ›  dshkol

dplyr延迟调用中的意外整洁评估行为

  •  0
  • dshkol  · 技术社区  · 7 年前

    我有一个函数,它接受一个数据框架和几个变量,我希望它使用整洁的评估原则生成一组滞后变量。它的简单形式如下:

    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 回复  |  直到 7 年前
        1
  •  4
  •   Maurits Evers    7 年前

    你正在混合准引号语法。或者

    • 代替 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 把它们变成 恩阔

      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
      
        2
  •  1
  •   akrun    7 年前

    我们可以创建一个函数,它可以同时接受无引号和带引号的字符串

    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