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

如何在R Plotly分组柱状图中对齐散点轨迹

解决Plotly分组柱状图中散点与对应年份柱子对齐的问题

问题核心

制作按年份分组的残疾人收入来源柱状图时,添加非残疾人的散点对比,散点默认落在x轴类别中心,无法和对应年份的柱子对齐。

解决方案思路

Plotly的分组柱状图中,每个x类别下的多组柱子会被分配相对偏移量(比如3组对应-0.2、0、0.2,以保持类别中心对齐)。要让散点和对应年份的柱子对齐,需要给非残疾人数据计算对应的x轴偏移位置,而非直接使用分类标签。

具体步骤

  1. 为每个年份分配固定偏移量:根据年份数量设置对应偏移值(3个年份可设为c(-0.2, 0, 0.2))。
  2. 获取x轴分类标签的数值索引:Plotly将分类x轴转换为0、1、2...的底层索引,通过match()函数得到每个类别的索引值(需减1适配Plotly的0起始规则)。
  3. 计算散点实际x位置:类别索引 + 对应年份的偏移量。

修改后的完整代码

先补充模拟的非残疾人数据(原数据仅包含残疾人),再调整代码逻辑:

library(plotly)
library(tidyr)

# 原始数据 + 模拟非残疾人数据
Figure16 <- structure(list(Disability = c("Disabled", "Disabled", "Disabled", "Non-disabled", "Non-disabled", "Non-disabled"), 
                           Year = c("2017/18", "2018/19", "2019/20", "2017/18", "2018/19", "2019/20"), 
                           `Wages and salaries` = c(0.32, 0.34, 0.37, 0.45, 0.47, 0.49), 
                           `All Pensions` = c(0.34, 0.32, 0.31, 0.28, 0.26, 0.24), 
                           `All Social Security benefits` = c(0.37, 0.27, 0.23, 0.30, 0.22, 0.18), 
                           `Self employment income` = c(0.03, 0.03, 0.06, 0.08, 0.10, 0.12)), 
                      class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -6L))

# 数据整理
Figure16 <- pivot_longer(Figure16, cols=c('Wages and salaries','All Pensions','All Social Security benefits','Self employment income'), 
                         names_to='Sources', values_to='Rate')
Figure16$Rate <- as.numeric(Figure16$Rate) * 100

# 包装x轴标签
Figure16$wrappedy <- sapply(Figure16$Sources,
                            FUN = function(x) {paste(strwrap(x, width = 25), collapse = " <br> ")})

# 为年份分配偏移量:3个年份对应-0.2、0、0.2
year_offsets <- c("2017/18" = -0.2, "2018/19" = 0, "2019/20" = 0.2)
Figure16$x_offset <- year_offsets[as.character(Figure16$Year)]

# 获取每个x类别的底层数值索引(适配Plotly的0起始规则)
Figure16$x_index <- match(Figure16$wrappedy, unique(Figure16$wrappedy)) - 1

# 计算散点的实际x位置:索引 + 偏移
Figure16$scatter_x <- Figure16$x_index + Figure16$x_offset

# 绘制图表
Figure_16 <- plot_ly(Figure16[Figure16$Disability =="Disabled",],
                     x = ~wrappedy,
                     y = ~Rate,
                     type = 'bar',
                     color = ~Year,
                     colors = c("#8FAADC","#2F5597","#203864"),
                     name = ~Year,
                     marker = list(color = ifelse(Figure16$Year=="2017/18","#8FAADC",
                                                 ifelse(Figure16$Year=="2018/19","#2F5597",
                                                        ifelse(Figure16$Year=="2019/20","#203864",
                                                               ""))),
                                   pattern = list(shape = ifelse(Figure16$Year=="2017/18","x",
                                                                 ifelse(Figure16$Year=="2018/19","/",
                                                                        ""))),
                                   line = list(color = ifelse(Figure16$Year=="2017/18","#8FAADC",
                                                               ifelse(Figure16$Year=="2018/19","#2F5597",
                                                                      ifelse(Figure16$Year=="2019/20","#203864",
                                                                             ""))), width = 1.25))
)%>%
  # 添加散点:使用计算后的scatter_x作为x值
  add_trace(data = Figure16[Figure16$Disability =="Non-disabled",], 
            x = ~scatter_x, 
            y = ~Rate, 
            type = 'scatter',  
            mode = 'markers', 
            name = 'Non-disabled', 
            marker = list(size = 30, symbol ='line-ew-open', color = "#FFC000", line=list(color = "#FFC000"), width = 33))%>%
  # 配置x轴:保留分类标签显示
  layout(xaxis = list(title = "", ticktext = ~unique(wrappedy), tickvals = ~unique(x_index)),
         yaxis = list(title = "", rangemode='tozero', ticksuffix = "%"))%>%
  config(displayModeBar = FALSE)

关键说明

  • year_offsets:偏移量可根据年份数量调整,比如2个年份用-0.15和0.15,保证柱子间距合理。
  • scatter_x:通过数值索引加偏移,让散点精准对应同一年份的柱子位置。
  • layout中的ticktext和tickvals:确保x轴显示原始分类标签,而非底层数值索引。

该方法可复用在你需要制作的7个图表中,仅需根据年份数量调整偏移量即可。

内容的提问来源于stack exchange,提问作者Rory

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:07:02