【问题标题】:dplyr doesn't evaluate column name given tailored functiondplyr 不评估给定定制函数的列名
【发布时间】:2019-09-23 02:15:27
【问题描述】:

定制函数内的 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 到结束的列。我已经阅读了许多其他类似的帖子,但没有任何帮助。如果您能建议问题出在哪里,我将不胜感激。

【问题讨论】:

  • na.interpolation 来自哪里?如果来自库,请在顶部包含,以便其他人可以运行您的代码。
  • 您可以通过多种方式索引变量(grep("vari", names(data))which(names(data) == "vari")

标签: r function dplyr


【解决方案1】:

您也可以使用!!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

【讨论】:

    【解决方案2】:

    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)
    

    【讨论】:

    • 谢谢乔恩。我刚刚找到了一个可行的解决方案。这是 !!rlang::sym(vari) 的用法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2019-03-23
    • 2019-02-28
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多