如何通过 .dplyr 管道引用 data.frame 变量。以编程方式?

How to refer to a data.frame variable in a dplyr pipeline via . programmatically?

library(ggplot2)
library(dplyr)
library(scales)

data <- data.frame(THEME_NAME = c(rep("A", 10), rep("B", 20), rep("C", 15)))

data %>%
  group_by(THEME_NAME) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n)) %>%
  # THE NEXT LINE !!! #
  ggplot(., aes(x = reorder(THEME_NAME, desc(freq)), y = freq)) +
    geom_bar(stat="identity") +
    scale_y_continuous(labels=percent)

如何以编程方式引用 THEME_NAME?我可以 .$THEME_NAME,但我想称其为 .[1]select(., 1) 或类似性质的东西?

这样做的原因是我想在更大的上下文中使用这个管道——比如通过这个管道传递一堆因子变量。类似于:vars.to.plot <- sapply(data, is.factor) 然后 运行 vars.to.plot 的每个元素通过此管道。

据我所知,这必须分三部分完成。我发现有一些限制,如果我弄错了,我将不胜感激。

data <- data.frame(THEME_NAME = c(rep("A", 10), rep("B", 20), rep("C", 15)))    
my_var <- names(data)[1]

df <- data %>%
  group_by_(my_var) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n)) %>%
  arrange(desc(freq))

df[[1]] <- factor(df[[1]], levels = unique(df[[1]]))

ggplot(df, aes_string(x = my_var, y = "freq")) +
  geom_bar(stat="identity") +
  scale_y_continuous(labels=percent)

为了解决所有问题,我 运行 遇到了这些问题:

  1. 没有办法阻止 ggplot 在调用之前不重置变量级别的情况下自动对 x 轴进行排序。 ggplot 调用中的唯一方法是使用 reorder,据我所知,它不能与 aes_string.
  2. 一起使用
  3. 我的另一个想法是使用 mutate 重置关卡。人们需要使用 dplyrExras 中的 s_mutate 函数来使用字符串,但从管道数据集中重置级别似乎对字符串不起作用。

声明在 mutate 中看起来像这样(顺便说一句,这很有效):

mutate(THEME_NAME = factor(THEME_NAME, levels=unique(THEME_NAME)))

但是对于接受版本的字符串,级别保持不变:

s_mutate(my_var = factor(my_var, levels = unique(my_var)))

所以你需要设置一个变量来保存分组变量的名称,因为在 summarize() 调用之后 "group by" 变量信息显然没有保存在 tbl_df 对象中.你可以这样做

varname<-"THEME_NAME"

data %>%
  group_by_(varname) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n)) %>%
  ggplot(eval(bquote(aes(x=reorder(.(as.name(varname)), desc(freq)), y=freq)))) +
    geom_bar(stat="identity") +
    scale_y_continuous(labels=percent)

此处使用 bquote() 动态构建 aes() 调用。这只是因为您要执行的 reorder() 步骤。否则使用 aes_string() 或其他东西会容易得多。

如果您总是想根据第一列重新排序(这意味着您永远不会按多个变量分组),您可以这样做

data %>%
  group_by(THEME_NAME) %>%
  summarise(n = n()) %>%
  mutate(freq = n / sum(n)) %>%
  {ggplot(., eval(substitute(aes(x=reorder(X, desc(freq)), y=freq), list(X=as.name(names(.)[1])))))  +
    geom_bar(stat="identity") +
    scale_y_continuous(labels=percent)}

不需要

这里分享的想法很有用,但这是我最终做的事情:

library(ggplot2)
library(dplyr)
library(scales)

data <- data.frame(THEME_NAME   = c(rep("A", 10), rep("B", 20), rep("C", 15)),
                   THEME_NAME_2 = c(rep("E", 5), rep("F", 40)),
                   Non_Factor   = 1:45)

factor.vars <- sapply(data, is.factor)
varnames    <- names(data)[factor.vars]

myReorder <- function(x) {
  factor(x, levels=names(sort(table(x), decreasing=TRUE)))
}


for (i in seq_along(varnames)) {
  data[, varnames[i]] <- myReorder(data[, varnames[i]])
}


for (i in seq_along(varnames)) {
  print(ggplot(data, aes_string(x = varnames[i], y = "..count../sum(..count..)")) + 
          geom_histogram())
}