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

Plotly预定义分位数分组箱线图的箱线颜色自定义问题

问题:Plotly基于预定义分位数的分组箱线图,按site_status设置箱线颜色

我用R的Plotly包,基于预定义分位数创建分组箱线图,想要依据site_status变量设置箱线的颜色。直接调用Plotly无法实现这个需求,尝试了两种方法都遇到问题:

尝试方法1:添加透明填充的新轨迹

这个方法在非分组场景下有效,但分组箱线图中会生成独立分组项,还会改变原有箱线的颜色。代码如下:

library(plotly)
library(dplyr)

# 创建模拟数据
set.seed(123)
site_name <- rep(paste0("site_", 1:5), each = 40)
site_type <- rep(c("A", "B"), each = 20, times = 5)
value <- runif(200, min = 0, max = 200) # 修正样本量匹配问题
df <- data.frame(site_name, site_type, value)

# 生成site_status
unique_combinations <- unique(df[c("site_name", "site_type")])
unique_combinations$site_status <- sample(c("Good", "Bad"), nrow(unique_combinations), replace = TRUE)
df <- df %>% left_join(unique_combinations, by = c("site_name", "site_type"))

# 计算分位数统计量
stats_df <- df %>%
  group_by(site_name, site_type) %>%
  summarise(
    lower_fence = quantile(value, probs = 0.05, type = 5, na.rm = TRUE),
    q1 = quantile(value, probs = 0.25, type = 5, na.rm = TRUE),
    median = quantile(value, probs = 0.5, type = 5, na.rm = TRUE),
    q3 = quantile(value, probs = 0.75, type = 5, na.rm = TRUE),
    upper_fence = quantile(value, probs = 0.95, type = 5, na.rm = TRUE),
    site_status = unique(site_status),
    .groups = 'drop'
  )

# 初始箱线图
fig <- plot_ly(data = stats_df, 
               x = ~site_name, 
               color = ~site_type,
               colors = c("blue","red"), 
               type = "box",
               lowerfence = ~lower_fence, 
               q1 = ~q1, 
               median = ~median,
               q3 = ~q3, 
               upperfence = ~upper_fence) %>%
  layout(boxmode = "group", boxgap = 1/5)

# 添加透明轨迹标记Bad状态
bad_data <- stats_df %>% filter(site_status == "Bad")
fig <- fig %>% plotly::add_trace(
  x = factor(bad_data$site_name),
  color = factor(bad_data$site_type),
  colors = c("blue","red"),
  type = "box",
  lowerfence = bad_data$lower_fence,
  q1 = bad_data$q1,
  median = bad_data$median,
  q3 = bad_data$q3,
  upperfence = bad_data$upper_fence,
  line = list(color = "green"),
  fillcolor = "rgba(255,0,0,0.0)",
  boxmean = FALSE,
  showlegend = TRUE,
  inherit = FALSE
)

fig

尝试方法2:plotly_build后处理

参考Stack Overflow的方案,但因为预定义分位数的数据结构不同,修改后不生效。代码如下:

built_fig <- plotly_build(fig)

lapply(1:length(stats_df$site_status),
       function(i){
         nm = stats_df$site_status[i]
         cr = ifelse(nm == "Good",
                     "#66FF66", "black")
         built_fig$x$data[[i]]$line$color <<- cr
       }
)

可行解决方案

问题核心:当使用color = ~site_type时,Plotly会将同一site_type的所有箱线打包成单个轨迹(trace),而非每个箱线对应一个轨迹。因此需要针对每个轨迹,给其中的每个箱线分配对应site_status的颜色向量。

完整代码如下:

library(plotly)
library(dplyr)

# 模拟数据与统计量计算部分同上方,此处省略重复代码

# 初始箱线图
fig <- plot_ly(data = stats_df, 
               x = ~site_name, 
               color = ~site_type,
               colors = c("blue","red"), 
               type = "box",
               lowerfence = ~lower_fence, 
               q1 = ~q1, 
               median = ~median,
               q3 = ~q3, 
               upperfence = ~upper_fence) %>%
  layout(boxmode = "group", boxgap = 1/5)

# 对plotly对象进行后处理
built_fig <- plotly_build(fig)

# 定义颜色映射规则
color_map <- c("Good" = "#66FF66", "Bad" = "black")

# 按site_type拆分统计数据,确保顺序与Plotly轨迹一致
stats_A <- stats_df %>% filter(site_type == "A") %>% arrange(site_name)
stats_B <- stats_df %>% filter(site_type == "B") %>% arrange(site_name)

# 修改第一个轨迹(site_type=A)的箱线颜色
built_fig$x$data[[1]]$line$color <- color_map[stats_A$site_status]
# 修改第二个轨迹(site_type=B)的箱线颜色
built_fig$x$data[[2]]$line$color <- color_map[stats_B$site_status]

# 可选:修改中位数线颜色
# built_fig$x$data[[1]]$median$color <- color_map[stats_A$site_status]
# built_fig$x$data[[2]]$median$color <- color_map[stats_B$site_status]

# 展示图形
built_fig

关键说明

  1. 分组箱线图中,每个color类别对应一个trace,需为每个trace的line.color赋值颜色向量(而非单个颜色值)。
  2. 必须通过arrange(site_name)保证统计数据的顺序与Plotly轨迹中箱线的顺序一致,避免颜色对应错误。
  3. 若需修改须线、中位数线等其他元素颜色,直接修改对应属性即可(如median$color)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 11:29:54