ggplot按值排序后图例顺序异常致geom_area重叠问题咨询
问题根源与规范解决方法
这个问题我之前也碰到过,核心原因其实是ggplot2(包括ggplotly)的绘图堆叠顺序、图例顺序,默认是由Contas.Resultado列的因子水平顺序决定的,而不是你数据框的行排序。
哪怕你已经把数据框按Valor升序排好了,但如果Contas.Resultado是字符型,ggplot会默认按字母顺序生成因子水平;如果它已经是因子,但水平顺序没和你想要的堆叠顺序对齐,就会出现图层重叠、图例顺序混乱的问题——比如本该在底层(Valor较小)的类别被放到了上层,盖住了下面的区域。
规范解决方法
推荐用以下几种方式,从根源上对齐因子水平顺序、绘图顺序和图例顺序:
1. 用forcats::fct_reorder自动调整因子水平(最便捷)
forcats包的fct_reorder函数可以直接根据Valor的值来重新排序Contas.Resultado的因子水平,完美匹配你的需求:
library(forcats) library(dplyr) # 按Valor升序排列Contas.Resultado的因子水平 tbl1 <- tbl1 %>% mutate(Contas.Resultado = fct_reorder(Contas.Resultado, Valor, .desc = FALSE)) # 再运行你的绘图代码 ggplotly( tbl1 %>% ggplot(aes(Ano, Valor)) + geom_area(aes(fill = Contas.Resultado), position = position_dodge(width = 0), stat = "identity") + scale_x_yearmon() + xlab("") + ylab("R$ (milhões)") )
这里.desc = FALSE表示按Valor从小到大排序,这样绘图时Valor小的类别会被放在底层,大的在上层,不会出现重叠,图例顺序也会和堆叠顺序一致。
2. 手动指定因子水平(无需额外包)
如果你不想用forcats,可以手动提取排序后的类别顺序,再转为因子:
# 提取已经按Valor升序排列的Contas.Resultado唯一值 ordered_categories <- unique(tbl1$Contas.Resultado) # 将Contas.Resultado转为因子,指定水平顺序 tbl1 <- tbl1 %>% mutate(Contas.Resultado = factor(Contas.Resultado, levels = ordered_categories)) # 后续绘图代码不变
3. 仅调整图例顺序(不推荐,治标不治本)
如果你不想修改数据,也可以在ggplot中通过scale_fill_discrete调整图例顺序,但这不会改变绘图堆叠顺序,可能依然存在重叠问题,所以只推荐临时用:
ggplotly( tbl1 %>% ggplot(aes(Ano, Valor)) + geom_area(aes(fill = Contas.Resultado), position = position_dodge(width = 0), stat = "identity") + scale_x_yearmon() + scale_fill_discrete(breaks = unique(tbl1$Contas.Resultado)) + # 对齐图例顺序 xlab("") + ylab("R$ (milhões)") )
你之前通过修改df$Contas.Resultado解决问题,本质就是手动调整了这个列的因子水平顺序,让它和你想要的堆叠顺序对齐了。上面的方法是更规范、可复用的处理方式,避免手动调整的不确定性。
内容的提问来源于stack exchange,提问作者Gui_99
相关产品推荐
相关产品推荐

