Open
Description
A Dash user is seeing an error from pandas
without ever directly importing pandas
, just dash
, plotly
, and numpy
. https://community.plotly.com/t/callback-error-when-plotting-multiple-graph-objects/38756
The error occurs inside plotly
when the Dash app tries to render one of the plots in a callback:
Traceback (most recent call last):
File "/Users/alex/plotly/fiddle/f.py", line 74, in update_dist_plot
"data": [go.Bar(x=bins, y=counts)],
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/plotly/graph_objs/__init__.py", line 93149, in __init__
self["x"] = x if x is not None else _v
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/plotly/basedatatypes.py", line 3490, in __setitem__
self._set_prop(prop, value)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/plotly/basedatatypes.py", line 3772, in _set_prop
val = validator.validate_coerce(val)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/_plotly_utils/basevalidators.py", line 385, in validate_coerce
v = copy_to_readonly_numpy_array(v)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/_plotly_utils/basevalidators.py", line 93, in copy_to_readonly_numpy_array
if pd and isinstance(v, (pd.Series, pd.Index)):
AttributeError: module 'pandas' has no attribute 'Series'
That's the error I see - the OP's error message is a little more extensive, which is a little funny because we both report pandas v1.0.3
AttributeError: partially initialized module ‘pandas’ has no attribute ‘Series’ (most likely due to a circular import)
I can reproduce locally with this app:
import dash_core_components as dcc
import dash_html_components as html
from dash import Dash
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import numpy as np
app = Dash(__name__)
app.layout = html.Div(
[
html.Div(
[
html.Br(),
html.Label("Plotting Options"),
dcc.RadioItems(
id="trunk-angle-radio",
options=[
{"label": "Sagittal", "value": "Sagittal"},
{"label": "Lateral", "value": "Lateral"},
{"label": "Twist", "value": "Twist"},
],
value="Sagittal",
),
]
),
html.Div(
[
html.Div(
[dcc.Graph(id="trunk-angle-plot")],
style={"width": "48%", "display": "inline-block"},
),
html.Div(
[dcc.Graph(id="trunk-angle-dist")],
style={"width": "48%", "display": "inline-block", "float": "right"},
),
]
),
html.Div(
[
html.Label("Data Statistics"),
html.Div(id="data-stats-div", style={"padding": 10}),
]
),
]
)
@app.callback(
Output("trunk-angle-plot", "figure"), [Input("trunk-angle-radio", "value")]
)
def update_angle_plot(radio_option):
(x, y) = get_trunk_angles(radio_option)
fig = {
"data": [go.Scatter(x=x, y=y, mode="lines+markers")],
"layout": go.Layout(
title="Trunk Angle Time Series Plot",
xaxis={"title": "Time (sec)"},
yaxis={"title": "Degrees"},
),
}
return fig
@app.callback(
Output("trunk-angle-dist", "figure"), [Input("trunk-angle-radio", "value")]
)
def update_dist_plot(radio_option):
(x, y) = get_trunk_angles(radio_option)
counts, bins = np.histogram(y, bins=range(-90, 91, 30))
bins = bins + (bins[1] - bins[0]) / 2
# print(counts, bins)
fig = {
"data": [go.Bar(x=bins, y=counts)],
"layout": go.Layout(
title="Trunk Angle Distributions",
xaxis={
"title": "Bin midpoint (degrees)",
"tickmode": "array",
"tickvals": bins,
"ticktext": [str(int(bin)) for bin in bins],
},
yaxis={"title": "Percentage of time"},
),
}
return fig
@app.callback(
Output("data-stats-div", "children"), [Input("trunk-angle-radio", "value")]
)
def update_stats(radio_option):
(x, y) = get_trunk_angles(radio_option)
stats_div = [
html.Div("Minimum: {}".format(np.min(y)), id="trunk-angle-dist-min"),
html.Div("Maximum: {}".format(np.max(y)), id="trunk-angle-dist-max"),
html.Div("Mean: {:.2f}".format(np.mean(y)), id="trunk-angle-dist-mean"),
html.Div(
"Standard Deviation: {:.2f}".format(np.std(y)), id="trunk-angle-dist-std"
),
html.Div(
"Range: {}".format(np.max(y) - np.min(y)), id="trunk-angle-dist-range"
),
]
return stats_div
def get_trunk_angles(radio_option):
dummy_x = np.linspace(0, 50, 101)
if radio_option == "Sagittal":
dummy_y = np.random.randint(-90, 90, 101)
elif radio_option == "Lateral":
dummy_y = np.random.randint(-90, 90, 101)
elif radio_option == "Twist":
dummy_y = np.random.randint(-90, 90, 101)
return (dummy_x, dummy_y)
if __name__ == "__main__":
app.run_server(debug=True)