【问题标题】:Call many variables in a for loop with dplyr/ggplot function使用 dplyr/ggplot 函数在 for 循环中调用许多变量
【发布时间】:2018-11-23 16:30:00
【问题描述】:

有时在执行探索性分析或生成报告时,我们希望绘制许多变量的单变量分布。经过一些整洁的技巧后,我可以在情节上做这件事,但是有有序的因素,我想让它们在情节上保持有序。

因此,为了以更有效的方式完成它,我构建了一个简单的基于dplyr/ggplot 的函数。我使用vcd包的关节炎数据集在下面做了这个例子。

library(dplyr)
library(ggplot2)

data(Arthritis, package = "vcd")

head(Arthritis)

plotUniCat <- function(df, x) {
  x <- enquo(x)
  df %>%
    filter(!is.na(!!x)) %>%
    count(!!x) %>%
    mutate(prop = prop.table(n)) %>%
    ggplot(aes(y=prop, x=!!x)) +
    geom_bar(stat = "identity")
}

plotUniCat(Arthritis, Improved)

我可以用很短的方式绘制格式化图表,这很酷,但只有一个变量。

我尝试使用 for 循环调用多个变量,但它不起作用。代码运行,但没有任何反应。

variables <- c("Improved", "Sex", "Treatment")

for (i in variables) {
  plotUniCat(Arthritis, noquote(i))
}

我对此进行了搜索,但我仍然不清楚。有人知道我做错了什么或如何使它起作用吗?

提前致谢。

【问题讨论】:

  • 可能会发生一些事情。在情节调用周围打印: print(plotUniCat(Arthritis, noquote(i)) )
  • 使用print() 语句是@HarlanNelson 解决方案的一部分。这是最简单的方法,但前提是我与其他人提出的rlang::sym() 解决方案混合使用。如果我不将quo() 更改为sym(),则会返回“提供给连续刻度的离散值”错误。谢谢兄弟!

标签: r ggplot2 dplyr tidyeval


【解决方案1】:

我猜 OP 想将 plotUniCat 用于带引号和不带引号的变量名。如果我们改变函数,它对plotUniCat(Arthritis, Improved) 不起作用。

因此,除了更改函数,我们还可以将函数plotUniCat的调用方式更改为:

for (i in variables) {
    plotUniCat(Arthritis, !!rlang::sym(i))
}

但是,绘图是由for 生成但未返回的。我们可以使用print或者lapply来强制显示或者收集生成的图:

lapply(variables, function(i) plotUniCat(Arthritis, !!rlang::sym(i)))

【讨论】:

    【解决方案2】:

    将函数中的enquo改为sym,将变量字符串转换为符号。也就是说,

    plotUniCat <- function(df, x) {
      x <- sym(x)
      df %>%
        filter(!is.na(!!x)) %>%
        count(!!x) %>%
        mutate(prop = prop.table(n)) %>%
        ggplot(aes(y=prop, x=!!x)) +
        geom_bar(stat = "identity")
    }
    

    或者,更简洁地说,

    plotUniCat <- function(df, x) {
      x <- sym(x)
      df %>%
        filter(!is.na(!!x)) %>%
        ggplot(aes(x = as.factor(!!x))) +
        geom_histogram(stat = "count")
    }
    

    然后

    out <- lapply(variables, function(i) plotUniCat(Arthritis,i))
    

    最后,使用grid.arrange 显示绘图。例如

    library(gridExtra)
    do.call(grid.arrange, c(out, ncol = 2))
    

    【讨论】:

    • 您的回答与董先生的回答非常相似。两者都适用于我想要的。但是我通过用lapply() 代替循环而不是purrr::map()grid.arrange() 包含来标记你的正确,从而组织绘图输出。非常感谢!
    【解决方案3】:

    您需要使用rlang::sym 将字符串转换为符号而不是enquo。我将for 循环替换为purrr::map 以循环遍历variables

    library(tidyverse)
    
    data(Arthritis, package = "vcd")
    
    head(Arthritis)
    #>   ID Treatment  Sex Age Improved
    #> 1 57   Treated Male  27     Some
    #> 2 46   Treated Male  29     None
    #> 3 77   Treated Male  30     None
    #> 4 17   Treated Male  32   Marked
    #> 5 36   Treated Male  46   Marked
    #> 6 23   Treated Male  58   Marked
    
    plotUniCat2 <- function(df, x) {
      x <- rlang::sym(x)
      df %>%
        filter(!is.na(!!x)) %>%
        count(!!x) %>%
        mutate(prop = prop.table(n)) %>%
        ggplot(aes(y=prop, x=!!x)) +
        geom_bar(stat = "identity")
    }
    
    variables <- c("Improved", "Sex", "Treatment")
    
    variables %>% purrr::map(., ~ plotUniCat2(Arthritis, .x))
    #> [[1]]
    

    #> 
    #> [[2]]
    

    #> 
    #> [[3]]
    

    reprex package (v0.2.0) 于 2018 年 6 月 13 日创建。

    【讨论】:

    • 谢谢董!非常好用,但我更喜欢 Weihuang 的 lapply() 解决方案。
    猜你喜欢
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多