ggplot2 堆叠条形图,将 NA 放在顶部

ggplot2 stacked bar, put NA on top

答案 提供了很多关于在堆叠条形图中排序条形部分的重要信息。在尝试了各种选择并获得了我想要的大部分顺序之后,NA 一直出现在堆栈的底部,这是我不喜欢的。

ggplot(df, aes(x=time, fill=forcats::fct_rev(factor(able, levels=rev(likely))))) + 
  geom_bar() + 
  theme(axis.text.x = element_text(angle = 315, hjust = 0), 
        plot.margin = margin(10, 40, 10, 10))

x 轴上的 NA 在最后,这很棒。通常将 NA 放在最后可能很好。但是对于堆叠条,我认为开始是底部,结束是顶部(因为底部的东西更容易比较。)

(Marimekko 图表可能会更好,但在尝试让 ggmosaic 和其他各种东西起作用一段时间后我放弃了。)

编辑:我找到了一些我修改过的代码来制作 Marimekko 图表(想表扬一下,但忘记了在哪里找到它。)它确实把NA 在顶部。

df %>%
group_by(satisfied, time) %>%
summarise(n = n()) %>%
mutate(x.width = sum(n)) %>%

ggplot(aes(x=satisfied, y=n)) +
geom_col(aes(width=x.width, fill=time),
         colour = "white", size=2, position=position_fill(reverse = T)) +
geom_text(aes(label=n),
           position=position_fill(vjust = 0.5)) +
facet_grid(~ satisfied, space = 'free', scales='free', switch='x') +
#scale_x_discrete(name="a") +
scale_y_continuous(labels=scales::percent) +
theme(axis.text.x = element_blank(),
      axis.ticks.x = element_blank(),
      axis.title.y = element_blank(),
      strip.text = element_text(angle = 270, hjust = 0),
      strip.background = element_blank(),
      panel.spacing = unit(0,'pt'))

应@z-lin 的要求序列化数据:

> dput(df)
structure(list(explanatory = c(8L, 3L, 13L, 10L, 5L, 9L, NA, 
5L, 1L, 4L, 4L, 3L, 2L, 2L, 2L, NA, 2L, NA, 4L, 3L, 2L, NA, 6L, 
NA, 2L, 6L, 5L, 1L, 3L, 2L, 1L, NA, 3L, 2L, 5L, 6L, 3L, 7L, 13L, 
4L, 4L, 3L, 1L, 2L, 2L, NA, 7L, 1L, NA, 12L, 13L, 4L, 6L, 2L, 
3L, 1L, 1L, 1L, 3L, 9L, 6L, 4L, 5L, 2L, 10L, 4L, 7L, NA, 4L, 
5L, 1L, 7L, 12L, 4L, 1L, 2L, 5L, 3L, 13L, 6L, 13L, 4L, NA, 2L, 
7L, 4L, 12L, 3L, 2L, 5L, 9L, 6L, 13L, 2L, 12L, 4L, 13L, 2L, 7L, 
NA, NA, NA, 4L, 5L, NA, NA, 7L, 5L, 5L, NA, 2L, 4L, 5L, 13L, 
5L, 2L, 2L, 4L, 7L, 4L, 7L, 6L, 5L, 5L, NA, 3L, 2L, NA, 3L, 5L, 
11L, 2L, 2L, 3L, 3L, 9L, 1L, 2L, 3L, 5L, 12L, 2L, 5L, 3L, 5L, 
5L, 12L, 2L, 2L, 3L, 4L, 1L, 1L, 3L, 2L, 3L, 4L, 13L, 3L, 3L, 
NA, NA, 6L, 5L, 3L, 1L, 8L, 6L, 9L, 5L, 8L, 1L, 1L, 3L, 5L, 6L, 
3L, 1L, 1L, 8L, 4L, 13L, 13L, 4L, 2L, NA, 3L, 1L, 3L, 4L, 5L, 
1L, 5L, 8L, 1L, 4L, 5L, 4L, 4L, 12L, 9L, NA, 2L, NA, NA, 5L, 
4L, 1L, 12L, 6L, NA, NA, NA, 4L, 12L, NA, 4L, 2L, 11L, NA, 5L, 
2L, 2L, 1L, NA, 6L, NA, 12L, 3L, 2L, 4L, NA, 1L, 6L, 8L, NA, 
4L, 6L, 5L, 6L, NA, 4L, NA, 2L, 7L, 8L, 3L, 6L, NA, 4L, NA, 2L, 
6L, 4L, 5L, NA, 12L, 2L, 12L, 6L, 6L, 13L, NA, 3L, 4L, 2L, NA, 
11L, 12L, 4L, 8L, 5L, 1L, 5L, 1L, 1L, 7L, 4L, 1L, 2L, 7L, 2L, 
3L, 5L, NA, 5L, 4L, NA, 6L, 9L, 2L, 1L, NA, 5L, 4L, NA, 1L, 6L, 
5L, 2L, 9L, 4L, 5L, 3L, 5L, 10L, 6L, 4L, 12L, 3L, 12L, 2L, 1L, 
1L, 5L, 9L, 2L, 2L, 2L, NA, 11L, 4L, 9L, NA, 12L, 2L, 1L, 10L, 
4L, 3L, 5L, NA, 10L, 3L, 2L, 8L, 3L, 4L, 9L, 4L, 10L, 1L, 2L, 
6L, 13L, 8L, 4L, 4L, 9L, 1L, 2L, 4L, 1L, 8L, 5L, 9L, 9L, 4L, 
4L, 6L, 3L, 1L, 2L, 5L, 3L, 1L, 1L, 12L, 1L, 2L, 3L, 4L, 10L, 
2L, 2L, 4L, 5L, 7L, 7L, 5L, 4L, 3L, 4L, 6L, 13L, 3L, NA, 3L, 
2L, 2L, 1L, NA, NA, 1L, NA, 4L, 2L, 8L, 4L, 8L, 3L, NA, 2L, 8L, 
8L, 4L, 5L, 4L, 2L, 4L, 2L, 5L, 1L, 6L, 5L, 7L, 4L, 3L, 5L, 3L, 
3L, 2L, 4L, 3L, 1L, 6L, 4L, 2L, 13L, 13L, NA, 5L, 5L, 2L, 5L, 
2L, 8L), response = c(3L, 5L, 4L, 4L, 4L, 3L, NA, 4L, 5L, 5L, 
4L, 4L, 5L, 5L, 4L, NA, 4L, NA, 2L, 5L, 4L, 4L, 5L, 4L, 5L, 3L, 
4L, 5L, 5L, 3L, 5L, 4L, 5L, 5L, 5L, 4L, 5L, 4L, 4L, 4L, 4L, 5L, 
5L, 5L, 4L, 4L, 4L, 4L, 5L, 4L, 4L, 5L, 5L, 4L, 4L, 4L, 4L, 5L, 
4L, 3L, 5L, 4L, 5L, 4L, 4L, 5L, 4L, 4L, 4L, 5L, 4L, 4L, 2L, 5L, 
5L, 4L, 3L, 5L, 4L, 5L, 4L, 5L, 4L, 4L, 4L, 5L, 3L, 4L, 3L, 4L, 
3L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 4L, NA, NA, NA, 5L, 4L, NA, NA, 
4L, 4L, 4L, NA, 4L, 5L, 3L, 4L, 4L, 5L, 5L, 5L, 4L, 5L, 5L, 5L, 
5L, 5L, 2L, 4L, 4L, NA, 4L, 5L, 4L, 3L, 4L, 4L, 5L, 4L, 4L, 4L, 
3L, 4L, 4L, 5L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 4L, 4L, 3L, 2L, 
5L, 5L, 5L, 5L, 2L, 5L, NA, NA, 4L, 3L, 4L, 4L, 4L, 4L, 2L, 3L, 
4L, 4L, 4L, 4L, 5L, 5L, 4L, 5L, 4L, 4L, 4L, 5L, 5L, 5L, 4L, 4L, 
3L, 4L, 4L, 5L, 4L, 5L, 4L, 4L, 4L, 4L, 4L, 5L, 4L, 4L, 3L, NA, 
5L, NA, NA, 3L, 3L, 5L, 4L, 4L, NA, 4L, NA, 5L, 4L, NA, 4L, 5L, 
5L, 3L, 4L, 4L, 4L, 4L, NA, 5L, NA, 4L, 4L, 4L, 5L, 5L, 4L, 4L, 
4L, 5L, 5L, 4L, 4L, 5L, NA, 5L, NA, 4L, 5L, 4L, 4L, 1L, NA, 4L, 
NA, 4L, 5L, 2L, 5L, NA, 4L, 4L, 5L, 4L, 4L, 4L, NA, 4L, 5L, 4L, 
3L, 5L, 5L, 5L, 2L, 3L, 5L, 5L, 4L, 4L, 5L, 4L, 3L, 4L, 4L, 5L, 
4L, 5L, NA, 5L, 5L, NA, 5L, 4L, 4L, 5L, NA, 5L, 4L, NA, 5L, 5L, 
5L, 4L, 3L, 5L, 4L, 4L, 2L, 5L, 4L, 4L, 5L, 4L, 5L, 4L, 5L, 4L, 
4L, 4L, 4L, 4L, 5L, NA, 4L, 4L, 5L, NA, 4L, 4L, 4L, 3L, 3L, 5L, 
5L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 4L, 4L, 5L, 5L, 5L, 
4L, 3L, 4L, 5L, 4L, 4L, 5L, 5L, 4L, 5L, 5L, 4L, 5L, 4L, 3L, 3L, 
4L, 5L, 3L, 4L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 
5L, 4L, 3L, 5L, 5L, 4L, 4L, 5L, NA, 4L, 4L, 4L, 5L, 3L, NA, 3L, 
3L, 4L, 5L, 5L, 5L, 4L, 5L, NA, 5L, 5L, 5L, 4L, 4L, 2L, 4L, 4L, 
5L, 5L, 4L, 4L, 5L, 5L, 4L, 3L, 5L, 5L, 4L, 4L, 4L, 5L, 4L, 4L, 
5L, 5L, 4L, 5L, NA, 4L, 4L, 4L, 4L, 3L, 4L), time = structure(c(8L, 
3L, 13L, 10L, 5L, 9L, NA, 5L, 1L, 4L, 4L, 3L, 2L, 2L, 2L, NA, 
2L, NA, 4L, 3L, 2L, NA, 6L, NA, 2L, 6L, 5L, 1L, 3L, 2L, 1L, NA, 
3L, 2L, 5L, 6L, 3L, 7L, 13L, 4L, 4L, 3L, 1L, 2L, 2L, NA, 7L, 
1L, NA, 12L, 13L, 4L, 6L, 2L, 3L, 1L, 1L, 1L, 3L, 9L, 6L, 4L, 
5L, 2L, 10L, 4L, 7L, NA, 4L, 5L, 1L, 7L, 12L, 4L, 1L, 2L, 5L, 
3L, 13L, 6L, 13L, 4L, NA, 2L, 7L, 4L, 12L, 3L, 2L, 5L, 9L, 6L, 
13L, 2L, 12L, 4L, 13L, 2L, 7L, NA, NA, NA, 4L, 5L, NA, NA, 7L, 
5L, 5L, NA, 2L, 4L, 5L, 13L, 5L, 2L, 2L, 4L, 7L, 4L, 7L, 6L, 
5L, 5L, NA, 3L, 2L, NA, 3L, 5L, 11L, 2L, 2L, 3L, 3L, 9L, 1L, 
2L, 3L, 5L, 12L, 2L, 5L, 3L, 5L, 5L, 12L, 2L, 2L, 3L, 4L, 1L, 
1L, 3L, 2L, 3L, 4L, 13L, 3L, 3L, NA, NA, 6L, 5L, 3L, 1L, 8L, 
6L, 9L, 5L, 8L, 1L, 1L, 3L, 5L, 6L, 3L, 1L, 1L, 8L, 4L, 13L, 
13L, 4L, 2L, NA, 3L, 1L, 3L, 4L, 5L, 1L, 5L, 8L, 1L, 4L, 5L, 
4L, 4L, 12L, 9L, NA, 2L, NA, NA, 5L, 4L, 1L, 12L, 6L, NA, NA, 
NA, 4L, 12L, NA, 4L, 2L, 11L, NA, 5L, 2L, 2L, 1L, NA, 6L, NA, 
12L, 3L, 2L, 4L, NA, 1L, 6L, 8L, NA, 4L, 6L, 5L, 6L, NA, 4L, 
NA, 2L, 7L, 8L, 3L, 6L, NA, 4L, NA, 2L, 6L, 4L, 5L, NA, 12L, 
2L, 12L, 6L, 6L, 13L, NA, 3L, 4L, 2L, NA, 11L, 12L, 4L, 8L, 5L, 
1L, 5L, 1L, 1L, 7L, 4L, 1L, 2L, 7L, 2L, 3L, 5L, NA, 5L, 4L, NA, 
6L, 9L, 2L, 1L, NA, 5L, 4L, NA, 1L, 6L, 5L, 2L, 9L, 4L, 5L, 3L, 
5L, 10L, 6L, 4L, 12L, 3L, 12L, 2L, 1L, 1L, 5L, 9L, 2L, 2L, 2L, 
NA, 11L, 4L, 9L, NA, 12L, 2L, 1L, 10L, 4L, 3L, 5L, NA, 10L, 3L, 
2L, 8L, 3L, 4L, 9L, 4L, 10L, 1L, 2L, 6L, 13L, 8L, 4L, 4L, 9L, 
1L, 2L, 4L, 1L, 8L, 5L, 9L, 9L, 4L, 4L, 6L, 3L, 1L, 2L, 5L, 3L, 
1L, 1L, 12L, 1L, 2L, 3L, 4L, 10L, 2L, 2L, 4L, 5L, 7L, 7L, 5L, 
4L, 3L, 4L, 6L, 13L, 3L, NA, 3L, 2L, 2L, 1L, NA, NA, 1L, NA, 
4L, 2L, 8L, 4L, 8L, 3L, NA, 2L, 8L, 8L, 4L, 5L, 4L, 2L, 4L, 2L, 
5L, 1L, 6L, 5L, 7L, 4L, 3L, 5L, 3L, 3L, 2L, 4L, 3L, 1L, 6L, 4L, 
2L, 13L, 13L, NA, 5L, 5L, 2L, 5L, 2L, 8L), .Label = c("0-15 minutes", 
"15-30 minutes", "30-45 minutes", "45-60 minutes (1 hour)", "60 minutes (1 hour) - 75 minutes", 
"75-90 minutes", "90-105 minutes", "105-120 minutes (2 hours)", 
"120 minutes (2 hours) - 135 minutes", "135-150 minutes", "150-165 minutes", 
"165-180 minutes (3 hours)", "More than 3 hours"), class = "factor"), 
    able = c("Neither Agree nor Disagree", "Strongly Agree", 
    "Agree", "Agree", "Agree", "Neither Agree nor Disagree", 
    NA, "Agree", "Strongly Agree", "Strongly Agree", "Agree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Agree", NA, 
    "Agree", NA, "Disagree", "Strongly Agree", "Agree", "Agree", 
    "Strongly Agree", "Agree", "Strongly Agree", "Neither Agree nor Disagree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Agree", "Strongly Agree", "Strongly Agree", 
    "Strongly Agree", "Agree", "Strongly Agree", "Agree", "Agree", 
    "Agree", "Agree", "Strongly Agree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Agree", "Agree", "Agree", "Strongly Agree", "Agree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Agree", "Agree", 
    "Agree", "Agree", "Strongly Agree", "Agree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Agree", "Strongly Agree", "Agree", "Agree", 
    "Strongly Agree", "Agree", "Agree", "Agree", "Strongly Agree", 
    "Agree", "Agree", "Disagree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Neither Agree nor Disagree", "Strongly Agree", 
    "Agree", "Strongly Agree", "Agree", "Strongly Agree", "Agree", 
    "Agree", "Agree", "Strongly Agree", "Neither Agree nor Disagree", 
    "Agree", "Neither Agree nor Disagree", "Agree", "Neither Agree nor Disagree", 
    "Agree", "Agree", "Agree", "Strongly Agree", "Strongly Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", NA, NA, NA, 
    "Strongly Agree", "Agree", NA, NA, "Agree", "Agree", "Agree", 
    NA, "Agree", "Strongly Agree", "Neither Agree nor Disagree", 
    "Agree", "Agree", "Strongly Agree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Strongly Agree", 
    "Strongly Agree", "Strongly Agree", "Disagree", "Agree", 
    "Agree", NA, "Agree", "Strongly Agree", "Agree", "Neither Agree nor Disagree", 
    "Agree", "Agree", "Strongly Agree", "Agree", "Agree", "Agree", 
    "Neither Agree nor Disagree", "Agree", "Agree", "Strongly Agree", 
    "Agree", "Agree", "Agree", "Agree", "Agree", "Agree", "Strongly Agree", 
    "Strongly Agree", "Agree", "Agree", "Neither Agree nor Disagree", 
    "Disagree", "Strongly Agree", "Strongly Agree", "Strongly Agree", 
    "Strongly Agree", "Disagree", "Strongly Agree", NA, NA, "Agree", 
    "Neither Agree nor Disagree", "Agree", "Agree", "Agree", 
    "Agree", "Disagree", "Neither Agree nor Disagree", "Agree", 
    "Agree", "Agree", "Agree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Strongly Agree", "Agree", "Agree", "Agree", "Strongly Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Agree", "Neither Agree nor Disagree", 
    "Agree", "Agree", "Strongly Agree", "Agree", "Strongly Agree", 
    "Agree", "Agree", "Agree", "Agree", "Agree", "Strongly Agree", 
    "Agree", "Agree", "Neither Agree nor Disagree", NA, "Strongly Agree", 
    NA, NA, "Neither Agree nor Disagree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Agree", "Agree", NA, "Agree", NA, "Strongly Agree", 
    "Agree", NA, "Agree", "Strongly Agree", "Strongly Agree", 
    "Neither Agree nor Disagree", "Agree", "Agree", "Agree", 
    "Agree", NA, "Strongly Agree", NA, "Agree", "Agree", "Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Agree", "Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Agree", "Strongly Agree", 
    NA, "Strongly Agree", NA, "Agree", "Strongly Agree", "Agree", 
    "Agree", "Strongly Disagree", NA, "Agree", NA, "Agree", "Strongly Agree", 
    "Disagree", "Strongly Agree", NA, "Agree", "Agree", "Strongly Agree", 
    "Agree", "Agree", "Agree", NA, "Agree", "Strongly Agree", 
    "Agree", "Neither Agree nor Disagree", "Strongly Agree", 
    "Strongly Agree", "Strongly Agree", "Disagree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Agree", "Strongly Agree", 
    "Agree", "Neither Agree nor Disagree", "Agree", "Agree", 
    "Strongly Agree", "Agree", "Strongly Agree", NA, "Strongly Agree", 
    "Strongly Agree", NA, "Strongly Agree", "Agree", "Agree", 
    "Strongly Agree", NA, "Strongly Agree", "Agree", NA, "Strongly Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Agree", "Agree", "Disagree", "Strongly Agree", 
    "Agree", "Agree", "Strongly Agree", "Agree", "Strongly Agree", 
    "Agree", "Strongly Agree", "Agree", "Agree", "Agree", "Agree", 
    "Agree", "Strongly Agree", NA, "Agree", "Agree", "Strongly Agree", 
    NA, "Agree", "Agree", "Agree", "Neither Agree nor Disagree", 
    "Neither Agree nor Disagree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Agree", "Agree", "Agree", "Agree", "Agree", "Strongly Agree", 
    "Strongly Agree", "Strongly Agree", "Strongly Agree", "Agree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Neither Agree nor Disagree", "Agree", "Strongly Agree", 
    "Agree", "Agree", "Strongly Agree", "Strongly Agree", "Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Strongly Agree", 
    "Agree", "Neither Agree nor Disagree", "Neither Agree nor Disagree", 
    "Agree", "Strongly Agree", "Neither Agree nor Disagree", 
    "Agree", "Neither Agree nor Disagree", "Agree", "Agree", 
    "Agree", "Agree", "Agree", "Agree", "Agree", "Agree", "Agree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Agree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Agree", "Strongly Agree", 
    NA, "Agree", "Agree", "Agree", "Strongly Agree", "Neither Agree nor Disagree", 
    NA, "Neither Agree nor Disagree", "Neither Agree nor Disagree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Strongly Agree", NA, "Strongly Agree", "Strongly Agree", 
    "Strongly Agree", "Agree", "Agree", "Disagree", "Agree", 
    "Agree", "Strongly Agree", "Strongly Agree", "Agree", "Agree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Neither Agree nor Disagree", 
    "Strongly Agree", "Strongly Agree", "Agree", "Agree", "Agree", 
    "Strongly Agree", "Agree", "Agree", "Strongly Agree", "Strongly Agree", 
    "Agree", "Strongly Agree", NA, "Agree", "Agree", "Agree", 
    "Agree", "Neither Agree nor Disagree", "Agree")), row.names = c(NA, 
-437L), class = "data.frame")

这里的问题是 factor() 默认排除 NA;你必须覆盖默认值。

这是在上面绘制 NAs:

likely <- c(NA, "Strongly Disagree", "Disagree", "Neither Agree nor Disagree", 
            "Agree", "Strongly Agree") 
library(ggplot2)
ggplot(df, aes(x = time, fill = factor(able, levels = likely, exclude = NULL)
)) +
  geom_bar() +
  theme(axis.text.x = element_text(angle = 315, hjust = 0),
        plot.margin = margin(10, 40, 10, 10))

此外,NA也可以移动到图例的顶部:

ggplot(df, aes(x = time, fill = factor(able, levels = likely, exclude = NULL)
)) +
  geom_bar() +
  theme(axis.text.x = element_text(angle = 315, hjust = 0),
        plot.margin = margin(10, 40, 10, 10)) +
  scale_fill_discrete(breaks = likely)