You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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)

尝试过以下方法但未达到预期效果:

  1. 直接用plotly绘制:
plotly::plot_ly(x=df$from,y=df$dist,split=df$to,color=df$to,type="bar")
  1. ggplot2结合fct_reorder:
library(ggplot2)
ggplot(df,aes(x=forcats::fct_reorder(from,dist),y=dist,fill=to))+geom_col(position='dodge')
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 08:36:04