使用 dplyr/ggplot 函数在 for 循环中调用多个变量

Call many variables in a for loop with dplyr/ggplot function

有时在执行探索性分析或生成报告时,我们想要绘制多个变量的单变量分布。我可以在一些巧妙的技巧之后对情节进行分面处理,但是有一些有序的因素,我想让它们在情节上保持有序。

因此,为了以更有效的方式完成它,我构建了一个简单的基于 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))
}

我搜索过这个,但我还是不清楚。有人知道我做错了什么或如何让它发挥作用吗?

提前致谢。

将函数中的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))

您需要使用 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-06-13。

我猜 OP 希望对带引号和不带引号的变量名使用 plotUniCat。如果我们更改函数,它将不适用于 plotUniCat(Arthritis, Improved).

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

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

但是,这些图是由 for 生成但未返回的。我们可以使用printlapply强制显示或收集生成的图:

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