如何在R的plotly分组条形图中为每个from分组按值排序to项
实现分组条形图中每个分组内类别按值排序(R语言)
问题背景
我在R的data.frame中存储了多组起点(from)到终点(to)的测量数据,希望绘制分组条形图,要求每个from分组下的to类别按dist值升序排列。
数据生成代码如下:
library(dplyr) set.seed(1) df <- expand.grid(paste0("g", 1:4),paste0("g", 1:6)) %>% dplyr::rename(from=Var1, to = Var2) %>% dplyr::mutate(dist = runif(24, 0, 1)) %>% dplyr::filter(as.character(from) != as.character(to)) %>% dplyr::arrange(from,dist)
尝试过以下方法但未达到预期效果:
- 直接用plotly绘制:
plotly::plot_ly(x=df$from,y=df$dist,split=df$to,color=df$to,type="bar")
- ggplot2结合fct_reorder:
library(ggplot2) ggplot(df,aes(x=forcats::fct_reorder(from,dist),y=dist,fill=to))+geom_col(position='dodge')
- ggplot2结合facet_grid:
ggplot(df,aes(x=from,y=dist,fill=to))+geom_col(position='dodge')+facet_grid(~from,scales="free",space="free")
解决方案
核心思路是:为每个from分组内的to创建一个按dist升序排列的有序因子,让绘图工具根据这个有序因子的水平来排序条形。
方法1:Plotly实现
先处理数据生成分组内有序的to因子,再传入plotly:
library(dplyr) library(forcats) library(plotly) # 生成每个from分组内按dist升序的to有序因子 df_sorted <- df %>% group_by(from) %>% mutate(to_ordered = fct_reorder(to, dist, .desc = FALSE)) %>% ungroup() # 绘制分组条形图 plot_ly(df_sorted, x = ~from, y = ~dist, split = ~to_ordered, color = ~to_ordered, type = "bar", hoverinfo = "text+y", text = ~paste("终点:", to_ordered)) %>% layout(barmode = "dodge", xaxis = list(title = "起点(from)"), yaxis = list(title = "距离(dist)"), legend = list(title = list(text = "终点(to)")))
方法2:ggplot2实现
可以用forcats::fct_reorder_within(需forcats版本≥0.5.0)快速生成分组有序因子,或者手动分组创建:
方式A:用fct_reorder_within
library(dplyr) library(forcats) library(ggplot2) df_sorted <- df %>% mutate(to_ordered = fct_reorder_within(to, dist, from, .desc = FALSE)) ggplot(df_sorted, aes(x = from, y = dist, fill = to_ordered)) + geom_col(position = position_dodge(preserve = "single")) + # 保持分组宽度一致 scale_fill_discrete(name = "终点(to)") + labs(x = "起点(from)", y = "距离(dist)") + theme_minimal()
方式B:手动分组创建有序因子(兼容旧版forcats)
library(dplyr) library(ggplot2) df_sorted <- df %>% group_by(from) %>% mutate(to_ordered = factor(to, levels = to[order(dist)])) %>% ungroup() ggplot(df_sorted, aes(x = from, y = dist, fill = to_ordered)) + geom_col(position = position_dodge(preserve = "single")) + scale_fill_discrete(name = "终点(to)") + labs(x = "起点(from)", y = "距离(dist)") + theme_minimal()
为什么之前的方法无效?
- 直接用plotly的
split=df$to:to是普通因子,默认按字母排序,不会识别分组内的dist顺序。 - 之前的ggplot2代码用
fct_reorder(from, dist):是对x轴的from分组排序,而非每个from下的to类别排序。 - facet_grid方法:仅拆分了绘图区域,但未对to的顺序做分组内调整,所以to仍按默认顺序排列。
内容的提问来源于stack exchange,提问作者dan
相关产品推荐
相关产品推荐

