Plotly px.line按标签分配颜色触发ValueError长度不匹配问题
报错原因
两个疑惑的核心原因都是对Plotly Express(以下简称px)的参数映射逻辑不熟悉:
- 为什么color参数被要求长度为73:px的参数默认按数据行做映射,如果你直接给
color传入一个数组/Series,px会认为你要给每一行数据单独指定颜色,因此会要求该数组长度和数据集行数(也就是你x轴的73个采样点长度)完全一致。你传入的是长度为7的列名数组,长度不匹配自然触发报错。 wide_variable_0到wide_variable_6的来源:你给y参数传入了7个独立的序列(分别来自7个不同的DataFrame),px接收多y序列的宽格式输入时,会自动给这7个序列生成从0开始编号的临时列名,也就是报错里提到的wide_variable系列字段,用来内部区分不同折线。
另外你的代码本身存在逻辑偏差:你传入的color=df.columns[8:]是当前df的7个列名,但你实际绘图用的y序列根本不是取自当前df的这7个列,而是来自其他7个DataFrame的字段,这个传参本身就不符合px的参数要求。
解决方案
两种常用方案,按需选择即可:
方案1:转换为长表格式(官方推荐)
px对长表格式的支持最好,不需要额外调整轨迹属性,逻辑最清晰:
- 先把所有要绘制的y序列和对应的x轴数据整合到同一个DataFrame中
- 用pandas的
melt方法把宽表转为长表,新增一列用来区分不同折线的分组 - 绘图时直接把分组列传给
color参数即可
参考代码:
import pandas as pd import plotly.express as px # 整合所有绘图用到的序列到统一数据表 plot_data = pd.DataFrame({ "semana_epidemiologica": df.semana_epidemiologica, "sin_vac_uci": ejey.sin_vac_uci, "una_dosis_uci": ejey2.una_dosis_uci, "dos_dosis_uci": ejey3.dos_dosis_uci, "dos_dosis_comp_uci": ejey4.dos_dosis_comp_uci, "dosis_unica_uci": ejey5.dosis_unica_uci, "dosis_unica_comp_uci": ejey6.dosis_unica_comp_uci, "dosis_ref_comp_uci": ejey7.dosis_ref_comp_uci }) # 宽表转长表 long_data = plot_data.melt( id_vars="semana_epidemiologica", var_name="vac_group", value_name="uci_incidence" ) # 绘图,color直接指定分组列即可自动分配颜色和标签 fig = px.line( long_data, x="semana_epidemiologica", y="uci_incidence", color="vac_group", title="Incidencia en UCI" ) # 如果需要自定义标签,直接把vac_group列的值替换成你要的df.columns[8:]对应文本即可 fig.show()
方案2:直接修改绘图后的轨迹属性
如果不想做数据格式转换,可以先按原来的方式绘图(不传color参数),再按y序列的传入顺序,逐个修改每条折线的名称和颜色:
import plotly.express as px fig = px.line( df, y = [ ejey.sin_vac_uci, ejey2.una_dosis_uci, ejey3.dos_dosis_uci, ejey4.dos_dosis_comp_uci, ejey5.dosis_unica_uci, ejey6.dosis_unica_comp_uci, ejey7.dosis_ref_comp_uci ], x = df.semana_epidemiologica, title='Incidencia en UCI' ) # 自定义标签和颜色,顺序必须和上面传入y的顺序完全对应 custom_labels = df.columns[8:].tolist() # 这里可以替换成你需要的自定义颜色色值 custom_colors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2"] for idx, trace in enumerate(fig.data): trace.name = custom_labels[idx] trace.line.color = custom_colors[idx] fig.show()
内容的提问来源于stack exchange,提问作者MrPie
相关产品推荐
相关产品推荐

