对注解扩展函数的惰性求值

Lazy evaluation to annotations expanding function

我写了一个函数来扩展组内的注释。

function(data, group_col, expand_col){
  data %>%
    dplyr::group_by(!!rlang::ensym(group_col)) %>%
    dplyr::mutate( 
      !!rlang::ensym(expand_col) = dplyr::case_when(
        !is.na(!!rlang::ensym(expand_col)) ~ 
          !!rlang::ensym(expand_col) ,
        any( !is.na(!!rlang::ensym(expand_col))  ) & is.na(!!rlang::ensym(expand_col)) ~ 
          paste(unique(unlist(str_split(na.omit(!!rlang::ensym(expand_col)), " ")) ), collapse = " "),
        TRUE ~ 
          NA_character_  
      )
    ) %>%
    dplyr::ungroup()
}

这应该是这样的:

> t <- structure(list(a = c("a", "b", "c", "d", "e", "f", "g", "h"), 
    b = c(1, 1, 1, 1, 2, 2, 2, 2), c = c(NA, NA, NA, "D", "E", 
    NA, NA, NA)), row.names = c(NA, -8L), class = c("tbl_df", 
"tbl", "data.frame"))
> t
# A tibble: 8 x 3
  a         b c    
  <chr> <dbl> <chr>
1 a         1 NA   
2 b         1 NA   
3 c         1 NA   
4 d         1 D    
5 e         2 E    
6 f         2 NA   
7 g         2 NA   
8 h         2 NA  

并让它成为:

> t %>%
+   dplyr::group_by(b) %>%
+   dplyr::mutate( 
+     c = dplyr::case_when(
+       !is.na(c) ~ c ,
+       any( !is.na(c)  ) & is.na(c) ~ 
+         paste(unique(unlist(str_split(na.omit(c), " ")) ), collapse = " "),
+       TRUE ~ 
+         NA_character_  
+     )
+   ) %>%
+   dplyr::ungroup()
# A tibble: 8 x 3
  a         b c    
  <chr> <dbl> <chr>
1 a         1 D    
2 b         1 D    
3 c         1 D    
4 d         1 D    
5 e         2 E    
6 f         2 E    
7 g         2 E    
8 h         2 E    

任何人都知道这种方法有什么问题,或者有任何更好的策略通过扩展一些先前分配的元素来分配组中的元素。

一种选择是使用 curly-curly ({{...}}) 以更紧凑的方式执行此操作

f1 <- function(data, group_col, expand_col){
  data %>%
    dplyr::group_by({{group_col}}) %>%
    dplyr::mutate( 
      {{expand_col}} := dplyr::case_when(
        !is.na({{expand_col}}) ~ 
          {{expand_col}} ,
      any( !is.na({{expand_col}})  ) & is.na({{expand_col}}) ~ 
        paste(unique(unlist(str_split(na.omit({{expand_col}}), " ")) ), 
                         collapse = " "),
      TRUE ~ 
        NA_character_  
    ))  %>%
    dplyr::ungroup()
}  



f1(t, b, c)
# A tibble: 8 x 3
#  a         b c    
#  <chr> <dbl> <chr>
#1 a         1 D    
#2 b         1 D    
#3 c         1 D    
#4 d         1 D    
#5 e         2 E    
#6 f         2 E    
#7 g         2 E    
#8 h         2 E