如何在函数内部的 dplyr 过滤器中将参数称为字符

How to refer to an argument as character in dplyr filter inside a function

我正在尝试构建一个函数来计算某些变量的百分比 - 但我很难在引号内将参数称为字符值,因为我需要在过滤器动词内使用它。我有下面的数据集。

e1_done <- structure(list(koen_new = c("Kvinde", "Kvinde", "Mand", "Kvinde", 
                                "Mand", "Mand", "Kvinde", "Kvinde", "Mand", "Mand", "Kvinde", 
                                "Kvinde", "Kvinde", "Mand", "Mand", "Mand", "Kvinde", "Kvinde", 
                                "Mand", "Kvinde", "Mand", "Mand", "Kvinde", "Kvinde", "Mand", 
                                "Mand", "Kvinde", "Mand", "Kvinde", "Kvinde", "Mand", "Kvinde", 
                                "Kvinde", "Mand", "Mand", "Kvinde", "Kvinde", "Mand", "Mand", 
                                "Mand", "Mand", "Mand", "Mand", "Mand", "Mand", "Kvinde", "Mand", 
                                "Kvinde", "Kvinde", "Kvinde"), 
frvlg_1 = structure(c(0, 0, 0, 
                                                                                     0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
                                                                                     0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 
                                                                                     0, 0, 0, 0, 0))), row.names = c(NA, -50L), class = c("tbl_df", "tbl", "data.frame"))

    # A tibble: 50 × 2
       koen_new frvlg_1
       <chr>      <dbl>
     1 Kvinde         0
     2 Kvinde         0
     3 Mand           0
     4 Kvinde         0
     5 Mand           0
     6 Mand           0
     7 Kvinde         1
     8 Kvinde         0
     9 Mand           0
    10 Mand           0
    # … with 40 more rows

我构建了以下函数:

per.gender <- function(x) {
  e1_done %>% 
    group_by(koen_new) %>% 
    mutate(total_n_gender = n()) %>% 
    group_by(koen_new,{{x}}) %>% 
    mutate(n_frvl = n()) %>% 
    dplyr::select(n_frvl, total_n_gender) %>% 
    mutate(procentandel = n_frvl/total_n_gender) %>% 
    distinct(koen_new, {{x}}, procentandel,.keep_all = TRUE) %>% 
    filter({{x}} == 1) %>% 
    ungroup() %>% 
    select(koen_new, procentandel) 
}

产生我想要的:

per.gender(frvlg_1) 

# A tibble: 2 × 2
  koen_new procentandel
  <chr>           <dbl>
1 Kvinde         0.0417
2 Mand           0.115 

但是,我也希望将列procentandel重命名为执行函数的每个变量的特定值,即我想查找密码本中的变量存储在另一个tibble中,如下所示:

codebook <- structure(list(Label = c("Frvlg: Kultur (Fx Museer, Lokalhistoriske Arkiver, Sangkor, Teater)", 
"Frvlg: Idræt (Fx Sportsklubber, Danseforeninger, Svømmehaller)", 
"Frvlg: Fritid i Øvrigt (Fx Hobbyforeninger, Slægtsforskning, Spejder)"
), Variable = c("frvlg_1", "frvlg_2", "frvlg_3")), row.names = c(NA, 
-3L), class = c("tbl_df", "tbl", "data.frame"))


# A tibble: 3 × 2
  Label                                                                 Variable
  <chr>                                                                 <chr>   
1 Frvlg: Kultur (Fx Museer, Lokalhistoriske Arkiver, Sangkor, Teater)   frvlg_1 
2 Frvlg: Idræt (Fx Sportsklubber, Danseforeninger, Svømmehaller)        frvlg_2 
3 Frvlg: Fritid i Øvrigt (Fx Hobbyforeninger, Slægtsforskning, Spejder) frvlg_3 

我可以用这个查找这个值,这是我想将列 procentandel 重命名为:

的字符值
codebook_e1 %>% filter(Variable == "frvlg_1") %>% select(Label) %>% pull()
[1] "Frvlg: Kultur (Fx Museer, Lokalhistoriske Arkiver, Sangkor, Teater)"

但是,我不知道如何在函数内的过滤动词中将 x 引用为字符值,以便引用密码本。我尝试了各种 eval 函数等等 - 但是,它似乎对我没有任何作用。

如果我在引号中添加第二个参数 x,它会起作用 - 但是我只希望函数中有一个参数。

我希望这个问题足够清楚!

使用 rlang::ensym()x 捕获为符号,然后您可以使用 as.character():

进行转换
library(tidyverse)

per.gender <- function(x) {
  new_name <- codebook_e1 %>% 
    filter(Variable == as.character(ensym(x))) %>% 
    select(Label) %>% 
    pull()

  e1_done %>% 
    group_by(koen_new) %>% 
    mutate(total_n_gender = n()) %>% 
    group_by(koen_new,{{x}}) %>% 
    mutate(n_frvl = n()) %>% 
    select(n_frvl, total_n_gender) %>% 
    mutate(procentandel = n_frvl/total_n_gender) %>% 
    distinct(koen_new, {{x}}, procentandel,.keep_all = TRUE) %>% 
    filter({{x}} == 1) %>% 
    ungroup() %>% 
    select(koen_new, !!new_name := procentandel) 
}

per.gender(frvlg_1) 

结果:

# A tibble: 2 x 2
  koen_new `Frvlg: Kultur (Fx Museer, Lokalhistoriske Arkiver, Sangkor, Teater)`
  <chr>                                                                    <dbl>
1 Kvinde                                                                  0.0417
2 Mand                                                                    0.115 

另请注意使用 !!:= 运算符以在最终 select() 语句中使用 new_name 引用的值 — 否则该列将被命名为“new_name”。