plot error bar with plotly express not work
Question:
I try to plot error bar with plotly express but it report error:
input element is 3 but it says error_y size is 6:
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
Code:
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")
Answers:
This is happening because px.scatter
expects that both error_y
and error_y_minus
parameters are (str or int or Series or array-like)
and it’s evaluating the length of the dictionary you passed to error_y
.
I believe you are mixing up the error_y
argument types for px.scatter
and go.Scatter
because you only pass a dictionary to the error_y parameter if you are using go.Scatter (as shown here).
If you want to keep using px.scatter
, you can achieve a negative error bar (and no positive error bar) the following way:
fig = px.scatter(
x=x,
y=y,
color=colors,
error_y=[0] * len(y),
error_y_minus=y
)
After making this change, your code runs and I replaced save_fig(fig,pngname)
with fig.show()
to check the output:
I try to plot error bar with plotly express but it report error:
input element is 3 but it says error_y size is 6:
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
Code:
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")
This is happening because px.scatter
expects that both error_y
and error_y_minus
parameters are (str or int or Series or array-like)
and it’s evaluating the length of the dictionary you passed to error_y
.
I believe you are mixing up the error_y
argument types for px.scatter
and go.Scatter
because you only pass a dictionary to the error_y parameter if you are using go.Scatter (as shown here).
If you want to keep using px.scatter
, you can achieve a negative error bar (and no positive error bar) the following way:
fig = px.scatter(
x=x,
y=y,
color=colors,
error_y=[0] * len(y),
error_y_minus=y
)
After making this change, your code runs and I replaced save_fig(fig,pngname)
with fig.show()
to check the output: