R 兰格:从……得到名字。。。NSE函数中带有冒号快捷键

R 兰格:从……得到名字。。。NSE函数中带有冒号快捷键,r,dplyr,rlang,nse,R,Dplyr,Rlang,Nse,我正在编写一个函数包,用于制作人口统计数据表。我有一个函数,缩写如下,我需要在几个列中(…)收集数据帧。诀窍是我希望保持这些列的名称的顺序,因为我需要在收集之后按顺序放置一列。在这种情况下,这些列是estimate,moe,share,sharemoe 库(tidyverse) 图书馆(rlang) 种族:8 x 6 #>区域变量估计moe份额moe #> #>1纽黑文怀特40164 1395 0.308 0.011 #>2纽黑文黑色42970 138

我正在编写一个函数包,用于制作人口统计数据表。我有一个函数,缩写如下,我需要在几个列中(
)收集数据帧。诀窍是我希望保持这些列的名称的顺序,因为我需要在收集之后按顺序放置一列。在这种情况下,这些列是
estimate
moe
share
sharemoe

库(tidyverse)
图书馆(rlang)
种族:8 x 6
#>区域变量估计moe份额moe
#>                      
#>1纽黑文怀特40164 1395 0.308 0.011
#>2纽黑文黑色42970 1383 0.33 0.011
#>3纽黑文亚洲6042697 0.046 0.005
#>4纽黑文拉丁裔37231 1688 0.286 0.013
#>5外圈白色164150 1603 0.87 0.008
#>6外圈黑色3471 677 0.018 0.004
#>7外圈亚洲9565 896 0.051 0.005
#>8外圈拉美裔8518 1052 0.045 0.006
在函数
collect\u arrange
中,我通过映射
rlang::exprs(…)
并转换为字符来获取
..
列的名称。要将这些列的名称提取为字符串是一项艰巨的任务,因此这可能是一个需要改进或重写的地方。但这是我想要的方式,使列
类型
作为一个因子,其级别为
估计
moe
共享
共享

gather\u arrange%forcats::fct\u rev())%%>%
dplyr::mutate(type=as.factor(type)%%>%forcats::fct_relevel(gather_names))%%>%
排列(类型)
}
种族%>%聚集\u排列(估计、moe、共享、共享)
#>#tibble:32 x 4
#>区域变量类型值
#>                   
#>1纽黑文怀特估计数40164
#>2纽黑文黑估计数42970
#>3纽黑文亚洲估计数6042
#>4纽黑文拉美裔估计数37231
#>5外环白色估计164150
#>6外环黑估计3471
#>7外环亚洲估计9565
#>8外环拉丁美洲估计数8518
#>9纽黑文怀特教育部1395
#>10纽黑文黑色moe 1383
#> # ... 还有22排
但是我想选择也使用冒号符号来选择列,即
estimate:sharemoe
,这样做相当于输入所有这些列名

race%>%gather\u arrange(估计值:sharemoe)
#>错误:结果1不是长度为1的原子向量
这会失败,因为它无法从
rlang::exprs(…)
中提取列名。如何使用此符号获取列名?提前谢谢

fun <- function(df, ...){
  as.character(substitute(list(...)))[-1] %>% 
    lapply(function(x)
      if(!grepl(':', x)) x
      else strsplit(x, ':')[[1]] %>%
            lapply(match, names(df)) %>%
            {names(df)[do.call(seq, .)]})%>% 
    unlist
}
names(race)
# [1] "region"   "variable" "estimate" "moe"      "share"    "sharemoe"    

fun(race, estimate:sharemoe, region)
# [1] "estimate" "moe"      "share"    "sharemoe" "region"  

fun(race, estimate, moe, share, sharemoe, region)
# [1] "estimate" "moe"      "share"    "sharemoe" "region" 

fun(race, moe, region:variable)
 # [1] "moe"      "region"   "variable"
原函数

gather_arrange <- function(df, ..., group = variable) {
  gather_cols <- rlang::quos(...)
  grp_var <- rlang::enquo(group)
  gather_names <- purrr::map_chr(rlang::exprs(...), as.character)

  df %>%
    tidyr::gather(key = type, value = value, !!!gather_cols) %>%
    dplyr::mutate(!!rlang::quo_name(grp_var) := !!grp_var %>% 
                    forcats::fct_inorder() %>% forcats::fct_rev()) %>%
    dplyr::mutate(type = as.factor(type) %>% forcats::fct_relevel(gather_names)) %>%
    arrange(type)
}

我们可以为具有
的情况创建
if
条件:
,从
选择
中获取要在
fct\u relevel中使用的列名('gather\u names')

gather_arrange <- function(df, group = variable, ...) {

    gather_cols <-  quos(...)
     grp_var <-  enquo(group)
    if(length(gather_cols)==1 && grepl(":", quo_name(gather_cols[[1]]))) {
         gather_cols <- parse_expr(quo_name(gather_cols[[1]]))
    }

    gather_names <- df %>%
                     select(!!! gather_cols) %>% 
                     names
    df %>%
         gather(key = type, value = value, !!!gather_cols)  %>%
         mutate(!!rlang::quo_name(grp_var) := !!grp_var %>% 
         fct_inorder() %>% 
         fct_rev()) %>%
         mutate(type = as.factor(type) %>%
                       fct_relevel(gather_names)) %>%
         arrange(type)             
    }
-检查

out1 <- gather_arrange(df = race, group = variable,
                     estimate, moe, share, sharemoe)
out1
# A tibble: 32 x 4
#   region     variable type      value
#   <chr>      <fct>    <fct>     <dbl>
# 1 New Haven  white    estimate  40164
# 2 New Haven  black    estimate  42970
# 3 New Haven  asian    estimate   6042
# 4 New Haven  latino   estimate  37231
# 5 Outer Ring white    estimate 164150
# 6 Outer Ring black    estimate   3471
# 7 Outer Ring asian    estimate   9565
# 8 Outer Ring latino   estimate   8518
# 9 New Haven  white    moe        1395
#10 New Haven  black    moe        1383
# ... with 22 more rows



out2 <- gather_arrange(df = race, group = variable, estimate:sharemoe)
identical(out1, out2)
#[1] TRUE
out1 <- gather_arrange2(df = race, group = variable,
                 estimate, moe, share, sharemoe, region)
out2 <- gather_arrange2(df = race, group = variable, estimate:sharemoe, region)

identical(out1, out2)
#[1] TRUE

out1我认为您正在寻找的函数是,select和rename在内部使用该函数来完成此任务。它返回变量名的字符向量。例如:

> tidyselect::vars_select(letters, g:j)
  g   h   i   j 
"g" "h" "i" "j"

这使您可以使用对
dplyr::select

有效的所有相同语法,真不敢相信这会如此简单!公平地说,这很简单,因为有人编写了一个完整的包来封装这个功能。
gather_arrange2 <- function(df, group = variable, ...) {

    gather_cols <-  quos(...)
    grp_var <-  enquo(group)

    gather_names <- df %>%
                     select(!!! gather_cols) %>% 
                     names
    gather_colsN <- lapply(gather_cols, function(x) parse_expr(quo_name(x)))

    df %>%
         gather(key = type, value = value, !!!gather_colsN)  %>%
         mutate(!!rlang::quo_name(grp_var) := !!grp_var %>% 
         fct_inorder() %>% 
         fct_rev()) %>%
         mutate(type = as.factor(type) %>%
                       fct_relevel(gather_names)) %>%
         arrange(type)             
    }       
out1 <- gather_arrange2(df = race, group = variable,
                 estimate, moe, share, sharemoe, region)
out2 <- gather_arrange2(df = race, group = variable, estimate:sharemoe, region)

identical(out1, out2)
#[1] TRUE
out1 <- gather_arrange2(df = race, group = variable,
                      estimate, moe, share, sharemoe)
out2 <- gather_arrange2(df = race, group = variable, estimate:sharemoe)
identical(out1, out2)
#[1] TRUE
> tidyselect::vars_select(letters, g:j)
  g   h   i   j 
"g" "h" "i" "j"