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

使用Plotly Python的go.Box绘制箱线图仅显示水平线问题求助

解决Plotly go.Box绘制分类箱线图仅显示水平线的问题

问题描述

使用Plotly的go.Box按分类变量绘制箱线图时,图表仅显示一条水平线,但使用px.express绘制相同数据则无此问题。以下是最小可复现示例(MRE):

多列循环绘图代码

import numpy as np
import pandas as pd
import plotly.graph_objects as go
from itertools import cycle

color_iter = cycle(['#1f77b4', '#ff7f0e', '#2ca02c'])

fares = [np.random.random() for g in np.arange(10000)]
types = ["new", "new", "old", "old", "really_old"] * 2000

df = pd.DataFrame({
    "bus_fares": fares,
    "bus_types": types
}) 

traces = []

for k in df["bus_types"].unique():
    trace = go.Box(
        x = [k],
        y = df[df["bus_types"]==k]["bus_fares"],
        marker={"color": next(color_iter)},
        name="bus_types",
        showlegend=False
    )

    traces.append(trace)

go.Figure(traces).show()

单个箱线图简化代码

x = "bus_types"
y = "bus_fares"
k = "old"

go.Figure(go.Box(x=[k], y=df[df[x]==k][y].values, name=x, showlegend=False)).show()

问题原因

问题出在x参数的设置:你给go.Box的x传入了长度为1的列表[k],但go.Box要求x的长度必须和y的长度完全匹配,这样才能将每个y值映射到对应的分类标签上。当长度不匹配时,Plotly无法正确解析数据,最终只显示一条水平线。

而px.express作为高层API,会自动处理数据的映射关系,无需手动保证x和y的长度一致,因此不会出现这个问题。

解决方法

只需要让x参数的长度和y保持一致即可,有两种简洁的实现方式:

方法1:构造与y长度相同的分类列表

修改循环中的x参数为:

x = [k] * len(df[df["bus_types"]==k]["bus_fares"])

方法2:直接传入对应的分类列子集

更推荐这种方式,直接从DataFrame中提取对应分类的bus_types列,长度自然与y匹配:

x = df[df["bus_types"]==k]["bus_types"]

修改后的完整循环代码示例

import numpy as np
import pandas as pd
import plotly.graph_objects as go
from itertools import cycle

color_iter = cycle(['#1f77b4', '#ff7f0e', '#2ca02c'])

fares = [np.random.random() for g in np.arange(10000)]
types = ["new", "new", "old", "old", "really_old"] * 2000

df = pd.DataFrame({
    "bus_fares": fares,
    "bus_types": types
}) 

traces = []

for k in df["bus_types"].unique():
    subset = df[df["bus_types"]==k]
    trace = go.Box(
        x = subset["bus_types"],  # 直接传入对应分类列
        y = subset["bus_fares"],
        marker={"color": next(color_iter)},
        name=k,  # 设置name为分类值,方便区分(可选)
        showlegend=False
    )

    traces.append(trace)

go.Figure(traces).show()

修改后的单个箱线图代码示例

x_col = "bus_types"
y_col = "bus_fares"
k = "old"
subset = df[df[x_col]==k]

go.Figure(go.Box(
    x = subset[x_col],
    y = subset[y_col].values,
    name=k,
    showlegend=False
)).show()

修改后即可正常显示完整的箱线图,包含中位数、四分位数、须线等元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:44:50