保持堆积图中的因子水平(ggplot)

时间:2018-07-12 17:47:09

标签: r ggplot2 bar-chart stacked-chart

ggplot中因子级别的排序是一个常见问题,关于它的帖子很多(例如Avoid ggplot sorting the x-axis while plotting geom_bar())。

这可能是重复的,但我没有遇到过这种特殊情况。

我正在尝试在堆积的条形图中保持X轴变量(“圆柱体”)的顺序。这是一个玩具示例。我转换了下面的变量以强调X轴上的字母顺序,即使该变量(圆柱体)在数据帧中之前已将显式顺序设置为“四个圆柱体”,“六个圆柱体”和“八个圆柱体”。

我在做什么错了?

mtcars <- mtcars %>% 
  mutate(cylinders = case_when(cyl == 4 ~ "Four cyl",
                               cyl == 6 ~ "Six cyl",
                               cyl == 8 ~ "Eight cyl"),
         cylinders = reorder(cylinders, cyl, mean)) %>% 
  mutate(engine = case_when(vs == 1 ~ "Manual",
                            vs == 0 ~ "Automatic"))

str(mtcars$cylinders)
levels(mtcars$cylinders)  # [1] "Four cyl"  "Six cyl"   "Eight cyl"
class(mtcars$cylinders)

facet_test <- function(df, gathvar) {

  gath <- enquo(gathvar)

  df %>% 
    select(cylinders, !!gath) %>%
    gather(key, value, -!!gath) %>%
    count(!!gath, key, value) %>%
    group_by(value) %>%
    mutate(perc = round(n/sum(n), 2) * 100) %>%  
    ggplot(aes(x = value, y = perc, fill = !!gath)) +
      geom_bar(stat = "identity")
}

facet_test(df = mtcars, gathvar = engine)

enter image description here

1 个答案:

答案 0 :(得分:0)

由于本文中的评论和@alistaire(https://stackoverflow.com/a/39157585/8453014),我得以找到解决方案。问题在于gather将因素强制转换为字符。

简单方案 如@aosmith所建议,请在mutate(value = factor(value, levels = levels(mtcars$cylinders)) )之后使用gather

具有多个变量的复杂示例 重要方面是:1)定义因子级别(无论在函数内部还是外部),以及2)将级别应用于“值”列。

这是一个使用三个变量并应用facet_wrap并排查看图的更复杂示例:

facet_test <- function(df, gathvar, legend_title) {
  gath <- enquo(gathvar)

# next two lines can go inside or outside of the function
  levels_cyl <- c("Four cyl", "Six cyl", "Eight cyl")
  levels_gears <- c("Three", "Four", "Five")

  df %>% 
    select(cylinders, gears, !!gath) %>%
    gather(key, value, -!!gath) %>%
    count(!!gath, key, value) %>%
    ungroup() %>% 
    mutate(value = factor(value, levels = unique(c(levels_cyl, levels_gears), 
                                                         fromLast = TRUE))) %>% 
    arrange(key, value) %>%  
    ggplot(aes(x = value, y = n, fill = !!gath)) +
      geom_bar(stat = "identity") +
      facet_wrap(~ key, scales = "free_x")
}

facet_test(df = mtcars, gathvar = engine)

[correct plot with factor levels in pre-defined order[1]