【问题标题】:How do I efficiently use different arguments for a custom function that relies on dplyr?如何有效地为依赖 dplyr 的自定义函数使用不同的参数?
【发布时间】:2021-09-30 14:43:41
【问题描述】:

有一个数据框,例如:

df <- data.frame(k = sample(1:2, 100, replace = TRUE),
                 l = sample(1:2, 100, replace = TRUE),
                 g = sample(1:3, 100, replace = TRUE, prob = c(0.2, 0.6, 0.2)))

我需要按 g 分组的 l 和 k 的比例图,所以我给自己写了一个函数:

library(tidyverse)

fun_gg_factor <- function(p) {
  df %>%
    group_by(g) %>%
    count({{p}}) %>%
    mutate(Anteil = n / sum(n)) %>%
    ggplot(aes(x = {{p}}, y = Anteil)) +
    geom_col(position = position_dodge()) +
    facet_grid(.~g)
}

它按预期工作:

fun_gg_factor(k)

这很好。但是我的 rl df 比 k 和 l 有更多的变量。多得多。所以我不想像这样手动调用函数几十次:

fun_gg_factor(k)
fun_gg_factor(l)
fun_gg_factor(m)
.
.
.
fun_gg_factor(z)

sapply() 及其形式浮现在脑海中:

sapply(c(k, l), fun_gg_factor)

这不起作用,因为 k 和 l 不是对象。即使他们是,那也不是我想要的。我不需要为 df$k 的每个元素绘制图 - 我想要不同列的图。
也许我尝试一个循环:

for (i in c(k, l)) {
  fun_gg_factor(i)
}

但是不,k 和 l 仍然不是对象。
显然我对这个问题的表述是缺乏的。我如何有效地为此或任何类似的自定义函数使用不同的参数?

【问题讨论】:

    标签: r ggplot2 dplyr rlang


    【解决方案1】:

    利用rlang 中的.data 代词,您可以将变量名称作为字符串传递给您的函数,这样就可以轻松地使用例如循环遍历一组变量。 lapply。为此,在您的函数中将 {{ p }} 替换为 .data[[p]]

    set.seed(42)
    
    df <- data.frame(
      k = sample(1:2, 100, replace = TRUE),
      l = sample(1:2, 100, replace = TRUE),
      g = sample(1:3, 100, replace = TRUE, prob = c(0.2, 0.6, 0.2))
    )
    
    library(ggplot2)
    library(dplyr)
    
    fun_gg_factor <- function(p) {
      df %>%
        group_by(g) %>%
        count(.data[[p]]) %>%
        mutate(Anteil = n / sum(n)) %>%
        ggplot(aes(x = .data[[p]], y = Anteil)) +
        geom_col(position = position_dodge()) +
        facet_grid(. ~ g)
    }
    
    lapply(names(df)[!names(df) %in% "g"], fun_gg_factor)
    #> [[1]]
    

    #> 
    #> [[2]]
    

    【讨论】:

      【解决方案2】:

      这是另一种以字符串形式强制评估用户定义参数的方法。我们首先使用rlang::sym 将参数转换为符号,然后使用称为bang-bang 运算符的!! 对其进行强制计算:

      library(rlang)
      
      fun_gg_factor <- function(p) {
        df %>%
          group_by(g) %>%
          count(!!sym(p)) %>%
          mutate(Anteil = n / sum(n)) %>%
          ggplot(aes(x = !!sym(p), y = Anteil)) +
          geom_col(position = position_dodge()) +
          facet_grid(.~ g)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-17
        • 1970-01-01
        • 1970-01-01
        • 2014-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多