dplyr不评估提供定制功能的列名

时间:2019-05-05 02:23:25

标签: r function dplyr

定制函数中的Dplyr不评估列。

我花了几个小时找出代码中的问题。我有一个具有几列的数据框(下面的示例),并在下面创建了传递数据框和列的函数。目标是进行滤波和变异以进行线性插值。但是,该函数不会读取参数列。

library(tidyverse)
library(imputeTS)
library(zoo)

dfm <- tbl_df(data.frame(country=rep('BGD', each=48), year=c(1970:2017), 
       STUNT=c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,                                                                 
       70.9,    NA, NA, NA, 63.4,   73.6,   71.5,   69.2,   67.3,    
       65.8,    63.8,   59.7, 59.3, 59.9,   50.8,   53.2,   51.4,   47.8,    
       50.5,    45.9,   45.1,   43.2,NA,    NA, NA, 41.4,   42,  
        38.7,   36.1,   NA, NA, NA, NA)))


vari = "STUNT"


data_impute<-        function(data, vari) {

                 data %>% 
                 select(country, year, paste0(vari)) %>%
                 group_by(country) %>% 
                 filter(seq_along(vari) >= min(which(!is.na(vari))) &
                        seq_along(vari) <= max(which(!is.na(vari)))) %>%
                mutate(vari= na.interpolation(vari, option="linear")) %>%
                select(country, year, paste0(vari)) %>%
                 ungroup()
               }

当使用数据执行该函数时,它为STUNT列提供字符串“ STUNT”。我看到里面的dplyr操作不会评估从group_by到结尾的列。我读过许多其他类似的文章,但没有帮助。如果您能建议问题出在哪里,我将不胜感激。

2 个答案:

答案 0 :(得分:1)

https://tidyeval.tidyverse.org/sec-why-how.html

dplyr使用了一种“非标准评估”形式,这种形式在许多情况下非常方便,但是当您希望将其用于编程时,可以进行更多的工作。我认为以下代码可以正常工作,大概是另一个包中的na.interpolation函数除外。我采用的方法是在变量上方“引用”变量,然后使用!!! (“ bang bang”)运算符在需要的地方取消报价。

data_impute<-        function(data, vari) {
  vari_quo <- enquo(vari)
  data %>% 
    select(country, year, paste0(!!vari_quo)) %>%
    group_by(country) %>% 
    filter(seq_along(!!vari_quo) >= min(which(!is.na(!!vari_quo))) &
             seq_along(!!vari_quo) <= max(which(!is.na(!!vari_quo)))) %>%
    # skipped next line b/c I don't have na.interpolation function
    # mutate(!!vari_quo := na.interpolation(!!vari_quo, option="linear")) %>%
    select(country, year, paste0(!!vari_quo)) %>%
    ungroup()
}

data_impute(dfm, vari)

答案 1 :(得分:0)

您也可以使用!!rlang::ensym。这接受参数为文字或字符串。

data_impute<-function(data, vari) {

  data %>% 
    select(country, year, !!rlang::ensym(vari)) %>%
    group_by(country) %>% 
    filter(seq_along(!!rlang::ensym(vari)) >= min(which(!is.na(!!rlang::ensym(vari)))) &
             seq_along(!!rlang::ensym(vari)) <= max(which(!is.na(!!rlang::ensym(vari))))) %>%
    mutate(vari := na_interpolation(!!rlang::ensym(vari), option="linear")) %>%
    select(country, year, !!rlang::ensym(vari)) %>%
    ungroup()
}

> head(data_impute(dfm, vari = STUNT))
# A tibble: 6 x 3
  country  year STUNT
  <fct>   <int> <dbl>
1 BGD      1985  70.9
2 BGD      1986  NA  
3 BGD      1987  NA  
4 BGD      1988  NA  
5 BGD      1989  63.4
6 BGD      1990  73.6

> head(data_impute(dfm, vari = "STUNT"))
# A tibble: 6 x 3
  country  year STUNT
  <fct>   <int> <dbl>
1 BGD      1985  70.9
2 BGD      1986  NA  
3 BGD      1987  NA  
4 BGD      1988  NA  
5 BGD      1989  63.4
6 BGD      1990  73.6