在ggplot2中手动更改复杂堆叠条形图上y轴项目的顺序

Posted

技术标签:

【中文标题】在ggplot2中手动更改复杂堆叠条形图上y轴项目的顺序【英文标题】:Manually change order of y axis items on complicated stacked bar chart in ggplot2 【发布时间】:2019-05-19 08:51:55 【问题描述】:

我遇到了一个问题,找不到解决方案。我在 Stack Overflow 和其他地方尝试了很多关于手动订购堆叠条形图的建议,因为这应该是一个非常简单的解决方法,但这些建议不适用于我从许多地方提取的大量复杂代码。我唯一的问题是 y 轴项目排序。

我正在制作一系列堆叠条形图,而 ggplot2 会根据我要绘制的数据框更改 y 轴上项目的顺序。我正在尝试制作 39 个这些地块,并希望它们都具有相同的顺序。我认为 ggplot2 只想按数字平均值或其他东西的升序绘制它们,但我希望所有条形图首先显示“鸟类倡导者”组,然后是“猫倡导者”组。 (这也是它们出现在我的数据框中的顺序,但是在绘图中的 coord_flip() 点处该顺序丢失了。)

我认为对数据框进行如此多的更改是为什么我不能只在最后添加一些简单的东西或使用 reorder() 函数。将东西添加到 aes() 中也不起作用,因为我创建的堆叠条形图似乎依赖于这些项目完全以某种方式。

这是我的一个数据框,其中 ggplot2 错误地对我的 y 轴项目进行排序,在“Bird Advocates”之前绘制“Cat Advocates”:

Group,Strongly Opposed,Opposed,Slightly Opposed,Neutral,Slightly Support,Support,Strongly Support
Bird Advocates,0.005473026,0.010946052,0.012509773,0.058639562,0.071149335,0.31118061,0.530101642
Cat Advocates,0.04491726,0.07013396,0.03624901,0.23719464,0.09141056,0.23404255,0.28605201

以下是所有将其转化为情节的代码:

library(ggplot2)
library(reshape2)
library(plotly)

#Importing data from a .csv file
data <- read.csv("data.csv", header=TRUE)

data$s.Strongly.Opposed <- 0-data$Strongly.Opposed-data$Opposed-data$Slightly.Opposed-.5*data$Neutral
data$s.Opposed <- 0-data$Opposed-data$Slightly.Opposed-.5*data$Neutral
data$s.Slightly.Opposed <- 0-data$Slightly.Opposed-.5*data$Neutral
data$s.Neutral <- 0-.5*data$Neutral
data$s.Slightly.Support <- 0+.5*data$Neutral
data$s.Support <- 0+data$Slightly.Support+.5*data$Neutral
data$s.Strongly.Support <- 0+data$Support+data$Slightly.Support+.5*data$Neutral

#to percents
data[,2:15]<-data[,2:15]*100

#melting
mdfr <- melt(data, id=c("Group"))
mdfr<-cbind(mdfr[1:14,],mdfr[15:28,3])
colnames(mdfr)<-c("Group","variable","value","start")

#remove dot in level names
mylevels<-c("Strongly Opposed","Opposed","Slightly Opposed","Neutral","Slightly Support","Support","Strongly Support")
mdfr$variable<-droplevels(mdfr$variable)
levels(mdfr$variable)<-mylevels

pal<-c("#bd7523", "#e9aa61", "#f6d1a7", "#999999", "#c8cbc0", "#65806d", "#334e3b")

ggplot(data=mdfr) +
  geom_segment(aes(x = Group, y = start, xend = Group, yend = start+value, colour = variable,
                   text=paste("Group: ",Group,"<br>Percent: ",value,"%")), size = 5) +
  geom_hline(yintercept = 0, color =c("#646464")) +
  coord_flip() + 
  theme(legend.position="top") +
  theme(legend.key.width=unit(0.5,"cm")) +
  guides(col = guide_legend(ncol = 12)) + #has 7 real columns, using to adjust legend position 
  scale_color_manual("Response", labels = mylevels, values = pal, guide="legend") +
  theme(legend.title = element_blank()) +
  theme(axis.title.x = element_blank()) +
  theme(axis.title.y = element_blank()) +
  theme(axis.ticks = element_blank()) +
  theme(axis.text.x = element_blank()) +
  theme(legend.key = element_rect(fill = "white")) +
  scale_y_continuous(breaks=seq(-100,100,100), limits=c(-100,100)) +  
  theme(panel.background = element_rect(fill = "#ffffff"),
        panel.grid.major = element_line(colour = "#CBCBCB"))

剧情:

【问题讨论】:

没有工作数据很难做到 - 使用像 dput(data) 这样的东西会很有用。 你试过类似scale_x_manual(breaks = c('bird advocates', 'cat advocates'))ggplot(data, aes(reorder('bird advocates', 'cat advocates')吗? 我粘贴了我正在导入的 .csv 文件的纯文本版本。我不知道如何将 .csv 文件上传到 Stack Exchange。我尝试了您的解决方案,这些解决方案与我之前尝试过的方法相似,但它们不起作用。正如我的帖子所说,我试图放入 ggplot 的 aes() 部分的任何内容都不适用于我的代码。 【参考方案1】:

我认为这可行,您可能需要玩转轴限制/中断:

library(dplyr)

mdfr <- mdfr %>%
  mutate(group_n = as.integer(case_when(Group == "Bird Advocates" ~ 2,
                         Group == "Cat Advocates" ~ 1)))

ggplot(data=mdfr) +
  geom_segment(aes(x = group_n, y = start, xend = group_n, yend = start + value, colour = variable,
               text=paste("Group: ",Group,"<br>Percent: ",value,"%")), size = 5) +
  scale_x_continuous(limits = c(0,3), breaks = c(1, 2), labels = c("Cat", "Bird")) + 
  geom_hline(yintercept = 0, color =c("#646464")) +
  theme(legend.position="top") +
  theme(legend.key.width=unit(0.5,"cm")) +
 coord_flip() + 
  guides(col = guide_legend(ncol = 12)) + #has 7 real columns, using to adjust legend position 
  scale_color_manual("Response", labels = mylevels, values = pal, guide="legend") +
  theme(legend.title = element_blank()) +
  theme(axis.title.x = element_blank()) +
  theme(axis.title.y = element_blank()) +
  theme(axis.ticks = element_blank()) +
  theme(axis.text.x = element_blank()) +
  theme(legend.key = element_rect(fill = "white"))+
  scale_y_continuous(breaks=seq(-100,100,100), limits=c(-100,100)) +
  theme(panel.background = element_rect(fill = "#ffffff"),
    panel.grid.major = element_line(colour = "#CBCBCB"))

产生这个情节:

【讨论】:

非常感谢您的修复!改变轴排序的常规方法都不起作用。【参考方案2】:

您希望按照希望条形出现的顺序来考虑“组”变量。

mdfr$Group <- factor(mdfr$Group, levels = c("Bird Advocates", "Cat Advocates")

【讨论】:

谢谢,但我之前尝试过类似的方法。在代码的#melting 部分末尾添加您的行会使整个图表无法正常工作,并且在级别部分中的#remove 点之后添加它不会更改 y 轴顺序。 对不起,我也遇到过类似的情况,但似乎总能解决它,所以我想先尝试一下。我并不怀疑它没有用,但我不确定为什么它会影响你描述它的放置位置。只要它在 #melting 部分的 colnames(mdfr) 行之后,它对输出的影响就不会有所不同 谢谢。我意识到这应该是一个很容易解决的问题,但是我正在使用的所有代码都阻止了我使用标准修复。

以上是关于在ggplot2中手动更改复杂堆叠条形图上y轴项目的顺序的主要内容,如果未能解决你的问题,请参考以下文章

在条形图上的 Plotly 中更改轴/图例名称

R语言ggplot2可视化:可视化离散(分类)变量的堆叠的直方图自定义堆叠直方图中不同分组条形的色彩(Histogram for Categorical Variable)自定义轴标签旋转的角度

堆叠条形图 ggplot2 - 重新排序填充

根据ggplot2中最后一个分面网格的递减值对条形图的Y轴进行排序

堆叠条形图的 Y 比例域最小值/最小值不为零; X 轴溢出

R语言ggplot2可视化:将条形图(bar plot)和线图(line plot)组合在一起并使用双Y轴(double y axis)进行可视化其中一个Y轴显示为百分比