使用Plotly Express绘制误差条报错:参数长度不匹配
问题:Plotly Express绘制误差条时出现长度不匹配错误
错误信息:
ValueError: All arguments should have the same length. The length of argument `error_y` is 6, whereas the length of previously-processed arguments ['x', 'y'] is 3
相关代码:
import plotly.express as px import pandas as pd import numpy as np from io import StringIO def save_fig(fig,pngname): fig.write_image(pngname,format="png", width=800, height=300, scale=1) print("[[%s]]"%pngname) #plt.show() return def date_linspace(start, end, steps): delta = (end - start) / (steps-1) increments = range(0, steps) * np.array([delta]*steps) return start + increments def plot_timedelta(x,y,colors,pngname): fig = px.scatter( x=x, y=y, color=colors, error_y=dict( type='data', symmetric=False, arrayminus=y, array=[0] * len(y), thickness=1, width=0, ), ) tickvals = date_linspace(x.min(),x.max(),15) print(x.min(),x.max()) layout =dict( title="demo", xaxis_title="X", yaxis_title="Y", title_x=0.5, margin=dict(l=10,t=20,r=0,b=40), height=300, xaxis=dict( tickangle=-25, tickvals = tickvals, ticktext=[d.strftime('%m-%d %H:%M:%S') for d in tickvals] ), yaxis=dict( showgrid=True, zeroline=False, showline=False, showticklabels=True ) ) fig.update_traces( marker_size=14, ) fig.update_layout(layout) save_fig(fig,pngname) return def get_delta(df): df['delta'] = df['ts'].diff().dt.total_seconds() df['prev'] = df['ts'].shift(1) print("delta min:",df['delta'].min()) print("delta max:",df['delta'].max()) #df = df[df['delta'] >= 40] return df data = """ts,source 2022-12-12 15:46:20.350,izat 2022-12-12 15:46:36.372,skyhook 2022-12-12 15:46:37.181,skyhook """ csvtext = StringIO(data) df = pd.read_csv(csvtext, sep=",") df['ts'] = pd.to_datetime(df['ts']) df = get_delta(df) df['delta'] = df['delta'].fillna(0) plot_timedelta(df['ts'],df['delta'],df['source'],"demo.png")
解决方案
错误原因
使用px.scatter时,color=colors会按colors的不同值生成多条独立轨迹(这里有2个分组:izat、skyhook)。直接在px.scatter的error_y中传入长度为3的数组,Plotly会将该数组重复应用到每条轨迹上,导致总长度变为3×2=6,与单条轨迹的长度不匹配,触发报错。
修改方法
方法1:通过update_traces设置误差条
先创建基础散点图,再用update_traces为所有轨迹统一设置误差条:
def plot_timedelta(x,y,colors,pngname): # 先创建无误差条的散点图 fig = px.scatter( x=x, y=y, color=colors, ) # 为每条轨迹添加误差条配置 fig.update_traces( marker_size=14, error_y=dict( type='data', symmetric=False, arrayminus=y, array=[0] * len(y), thickness=1, width=0, ) ) tickvals = date_linspace(x.min(),x.max(),15) print(x.min(),x.max()) layout =dict( title="demo", xaxis_title="X", yaxis_title="Y", title_x=0.5, margin=dict(l=10,t=20,r=0,b=40), height=300, xaxis=dict( tickangle=-25, tickvals = tickvals, ticktext=[d.strftime('%m-%d %H:%M:%S') for d in tickvals] ), yaxis=dict( showgrid=True, zeroline=False, showline=False, showticklabels=True ) ) fig.update_layout(layout) save_fig(fig,pngname) return
方法2:传入完整DataFrame让Plotly自动匹配
将所有数据(包括误差相关)存入DataFrame,直接传入px.scatter,Plotly会自动按分组匹配对应数据:
def plot_timedelta(df,pngname): fig = px.scatter( df, x='ts', y='delta', color='source', error_y=dict( type='data', symmetric=False, arrayminus='delta', # 直接引用DataFrame列名 array=[0]*len(df), thickness=1, width=0, ) ) tickvals = date_linspace(df['ts'].min(),df['ts'].max(),15) print(df['ts'].min(),df['ts'].max()) layout =dict( title="demo", xaxis_title="X", yaxis_title="Y", title_x=0.5, margin=dict(l=10,t=20,r=0,b=40), height=300, xaxis=dict( tickangle=-25, tickvals = tickvals, ticktext=[d.strftime('%m-%d %H:%M:%S') for d in tickvals] ), yaxis=dict( showgrid=True, zeroline=False, showline=False, showticklabels=True ) ) fig.update_traces(marker_size=14) fig.update_layout(layout) save_fig(fig,pngname) return # 调用时直接传入df plot_timedelta(df,"demo.png")
说明
当使用color分组时,Plotly会为每个分组创建独立轨迹。直接在px.scatter中设置error_y会导致误差数组被重复应用,引发长度冲突。通过上述两种方式,让误差数据与每条轨迹的实际数据长度匹配,即可解决问题。
内容的提问来源于stack exchange,提问作者lucky1928
相关产品推荐
相关产品推荐

