首页 > 解决方案 > 使用 {{foo}} 将变量名列表传递给函数

问题描述

问题

我想知道如何将变量名称列表传递给purrr::map2函数,以便迭代单独的数据框。

下面的input_table$key变量包含mpgdisp来自mtcars数据集。我认为变量的名称是作为字符串而不是变量名传递的。问题是我如何改变它,以便我的函数识别它们是变量名(?)。

在这个例子中,我试图对mtcars变量中的所有值求和,mpg并且disp低于一组数值阈值。来自的变量mtcars和相关阈值包含在input_table(下)中。

理想的结果

percentile   key    value  sum_y
  <fct>     <chr>   <dbl>  <dbl>
1 0.5        mpg    19.2   266.5
2 0.9        mpg    30.1   515.8
3 0.99       mpg    33.4   609.0
4 1          mpg    33.9   642.9
5 ...        ...    ...    ...

试图

library(dplyr)
library(purrr)
library(tidyr)
# Arrange a generic example
# Replicating my data structure
input_table <- mtcars %>% 
  as_tibble() %>% 
  select(mpg, disp) %>% 
  map_df(quantile, probs = c(0.5, 0.90, 0.99, 1)) %>% 
  mutate(
    percentile = factor(c(0.5, 0.90, 0.99, 1))
  ) %>% 
  select(
    percentile, mpg, disp
  ) %>% 
  gather(key, value, -percentile)

# Defining the function
test_func <- function(label_desc, threshold) {
  mtcars %>% 
    select({{label_desc}}) %>% 
    filter({{label_desc}} <= {{threshold}}) %>% 
    summarise(
      sum_y = sum(as.numeric({{label_desc}}), na.rm = T)
    )
}

# Demo'ing that it works for a single variable and threshold value
test_func(label_desc = mpg, threshold = 19.2)

# This is where I am having trouble
# Trying to iterate over multiple (mpg, disp) variables
map2(input_table$key, input_table$value, ~test_func(label_desc = .x, threshold = .y))

标签: rpurrr

解决方案


问题是 curly-curly ( {{}}) 用于未引用的变量,就像您在第一次尝试中使用的那样。在您的第二次尝试中,您将传递带引号的变量,而卷曲运算符不起作用。一个简单的解决方法是使用接受引用参数_at的变体。dplyr

test_func <- function(label_desc, threshold) {
  mtcars %>% 
    filter_at(label_desc, any_vars(. <= threshold)) %>% 
    summarise_at(label_desc, sum)
}

purrr::map2(input_table$key, input_table$value, test_func)

#[[1]]
#    mpg
#1 266.5

#[[2]]
#    mpg
#1 515.8

#[[3]]
#  mpg
#1 609

#[[4]]
#    mpg
#1 642.9

#[[5]]
#    disp
#1 1956.7
#.....

推荐阅读