I am trying to add a dropdown menu to a plotly line graph that updates the graph data source when selected. My data has 3 columns and looks as such:
1 Country Average House Price (£) Date
0 Northern Ireland 47101.0 1992-04-01
1 Northern Ireland 49911.0 1992-07-01
2 Northern Ireland 50174.0 1992-10-01
3 Northern Ireland 46664.0 1993-01-01
4 Northern Ireland 48247.0 1993-04-01
The Country column contains the 4 countries in the United Kingdom and is used for creating the separate lines for each using the color
parameter. I have 4 different dataframes for different housing types such as all_dwellings
, first_timebuyers
and when trying to specify the updatemenus
args it seems I cannot use the dataframe format. Here is the code to create the entire graph.
lineplt = px.line(data_frame = all_dwellings,
x='Date',
y='Average House Price (£)',
color= 'Country',
hover_name='Country',
color_discrete_sequence=['rgb(23, 153, 59)','rgb(214, 163, 21)','rgb(40, 48, 165)', 'rgb(210, 0, 38)']
)
updatemenus = [
{'buttons': [
{
'method': 'restyle',
'label': 'All Dwellings',
'args': [{'data_frame': all_dwellings}]
},
{
'method': 'restyle',
'label': 'First Time Buyers',
'args': [{'data_frame': first_buyers}]
}
],
'direction': 'down',
'showactive': True,
}
]
lineplt = lineplt.update_layout(
title_text='Average House Price in UK (£)',
title_x=0.5,
#plot_bgcolor= 'rgb(194, 208, 209)',
xaxis_showgrid=False,
yaxis_showgrid=False,
hoverlabel=dict(font_size=10, bgcolor='rgb(69, 95, 154)',
bordercolor= 'whitesmoke'),
legend=dict(title='Please click legend item to remove <br>or add to plot',
x=0,
y=1,
traceorder='normal',
bgcolor='LightSteelBlue',
xanchor = 'auto'),
updatemenus=updatemenus
)
lineplt = lineplt.update_traces(mode="lines", hovertemplate= 'Date = %{x} <br>' + 'Price = £%{y:.2f}')
lineplt.show()
However I get the following error:
TypeError: Object of type DataFrame is not JSON serializable
All the examples seem to convert items to lists but this doesn't seem to work with dataframe format. Could anybody help? If question not clear then please let me know.
EDIT - output of all_dwellings.head(20).to_dict()
{'Country': {0: 'Northern Ireland ', 1: 'Northern Ireland ', 2: 'Northern Ireland ', 3: 'Northern Ireland ', 4: 'Northern Ireland ', 5: 'Northern Ireland ', 6: 'Northern Ireland ', 7: 'Northern Ireland ', 8: 'Northern Ireland ', 9: 'Northern Ireland ', 10: 'Northern Ireland ', 11: 'Northern Ireland ', 12: 'Northern Ireland ', 13: 'Northern Ireland ', 14: 'Northern Ireland ', 15: 'Northern Ireland ', 16: 'Northern Ireland ', 17: 'Northern Ireland ', 18: 'Northern Ireland ', 19: 'Northern Ireland '}, 'Average House Price (£)': {0: 47101.0, 1: 49911.0, 2: 50174.0, 3: 46664.0, 4: 48247.0, 5: 54891.0, 6: 53773.0, 7: 57594.0, 8: 49804.0, 9: 58586.0, 10: 55154.0, 11: 55413.0, 12: 60239.0, 13: 59094.0, 14: 57131.0, 15: 61849.0, 16: 61951.0, 17: 61595.0, 18: 68705.0, 19: 74869.0}, 'Date': {0: Timestamp('1992-04-01 00:00:00'), 1: Timestamp('1992-07-01 00:00:00'), 2: Timestamp('1992-10-01 00:00:00'), 3: Timestamp('1993-01-01 00:00:00'), 4: Timestamp('1993-04-01 00:00:00'), 5: Timestamp('1993-07-01 00:00:00'), 6: Timestamp('1993-10-01 00:00:00'), 7: Timestamp('1994-01-01 00:00:00'), 8: Timestamp('1994-04-01 00:00:00'), 9: Timestamp('1994-07-01 00:00:00'), 10: Timestamp('1994-10-01 00:00:00'), 11: Timestamp('1995-01-01 00:00:00'), 12: Timestamp('1995-04-01 00:00:00'), 13: Timestamp('1995-07-01 00:00:00'), 14: Timestamp('1995-10-01 00:00:00'), 15: Timestamp('1996-01-01 00:00:00'), 16: Timestamp('1996-04-01 00:00:00'), 17: Timestamp('1996-07-01 00:00:00'), 18: Timestamp('1996-10-01 00:00:00'), 19: Timestamp('1997-01-01 00:00:00')}}
Output of first_buyers
{'Country': {0: 'Northern Ireland ', 1: 'Northern Ireland ', 2: 'Northern Ireland ', 3: 'Northern Ireland ', 4: 'Northern Ireland ', 5: 'Northern Ireland ', 6: 'Northern Ireland ', 7: 'Northern Ireland ', 8: 'Northern Ireland ', 9: 'Northern Ireland ', 10: 'Northern Ireland ', 11: 'Northern Ireland ', 12: 'Northern Ireland ', 13: 'Northern Ireland ', 14: 'Northern Ireland ', 15: 'Northern Ireland ', 16: 'Northern Ireland ', 17: 'Northern Ireland ', 18: 'Northern Ireland ', 19: 'Northern Ireland '}, 'Average House Price (£)': {0: 29280.0, 1: 32690.0, 2: 29053.0, 3: 30241.0, 4: 31032.0, 5: 31409.0, 6: 31299.0, 7: 28922.0, 8: 28621.0, 9: 31519.0, 10: 33497.0, 11: 35861.0, 12: 32472.0, 13: 34493.0, 14: 33662.0, 15: 32630.0, 16: 33426.0, 17: 37154.0, 18: 36555.0, 19: 36406.0}, 'Date': {0: Timestamp('1992-04-01 00:00:00'), 1: Timestamp('1992-07-01 00:00:00'), 2: Timestamp('1992-10-01 00:00:00'), 3: Timestamp('1993-01-01 00:00:00'), 4: Timestamp('1993-04-01 00:00:00'), 5: Timestamp('1993-07-01 00:00:00'), 6: Timestamp('1993-10-01 00:00:00'), 7: Timestamp('1994-01-01 00:00:00'), 8: Timestamp('1994-04-01 00:00:00'), 9: Timestamp('1994-07-01 00:00:00'), 10: Timestamp('1994-10-01 00:00:00'), 11: Timestamp('1995-01-01 00:00:00'), 12: Timestamp('1995-04-01 00:00:00'), 13: Timestamp('1995-07-01 00:00:00'), 14: Timestamp('1995-10-01 00:00:00'), 15: Timestamp('1996-01-01 00:00:00'), 16: Timestamp('1996-04-01 00:00:00'), 17: Timestamp('1996-07-01 00:00:00'), 18: Timestamp('1996-10-01 00:00:00'), 19: Timestamp('1997-01-01 00:00:00')}}
Plotly's python package is updated frequently. Run pip install plotly --upgrade to use the latest version.
Adding Traces New traces can be added to a plot_ly figure using the add_trace() method. This method accepts a plot_ly figure trace and adds it to the figure. This allows you to start with an empty figure, and add traces to it sequentially.
By default, text annotations have xref and yref set to "x" and "y" , respectively, meaning that their x/y coordinates are with respect to the axes of the plot.
I've made a preliminary setup using your full datasample, and I think I've got it figured out. The challenge here is that px.line
will group your data by the color
argument. And that makes it a bit harder to edit the data displayed using a dropdownmenu with a direct reference to the source of your px.line
plot.
But you can actually build multiple px.line
figures for the different datasets, and "steal" the data with the correct structure for your figure there. This will give you these figures for the different dropdown options:
I'm a bit worried that the second plot might be a bit off, but I'm using the date you've provided which looks like this for first_timebuyers
:
So maybe it makes sense after all?
Below is the complete code without your data. We can talk about the details and further tweaking tomorrow. Bye for now.
import numpy as np
import pandas as pd
import plotly.express as px
from pandas import Timestamp
all_dwellings=pd.DataFrame(<yourData>)
first_timebuyers = pd.DataFrame(<yourData>)
# datagrab 1
lineplt_all = px.line(data_frame = all_dwellings,
x='Date',
y='Average House Price (£)',
color= 'Country',
hover_name='Country',
color_discrete_sequence=['rgb(23, 153, 59)','rgb(214, 163, 21)','rgb(40, 48, 165)', 'rgb(210, 0, 38)']
)
# datagrab 2
lineplt_first = px.line(data_frame = first_timebuyers,
x='Date',
y='Average House Price (£)',
color= 'Country',
hover_name='Country',
color_discrete_sequence=['rgb(23, 153, 59)','rgb(214, 163, 21)','rgb(40, 48, 165)', 'rgb(210, 0, 38)']
)
### Your original setup
lineplt = px.line(data_frame = all_dwellings,
x='Date',
y='Average House Price (£)',
color= 'Country',
hover_name='Country',
color_discrete_sequence=['rgb(23, 153, 59)','rgb(214, 163, 21)','rgb(40, 48, 165)', 'rgb(210, 0, 38)']
)
updatemenus = [
{'buttons': [
{
'method': 'restyle',
'label': 'All Dwellings',
'args': [{'y': [dat.y for dat in lineplt_all.data]}]
},
{
'method': 'restyle',
'label': 'First Time Buyers',
'args': [{'y': [dat.y for dat in lineplt_first.data]}]
}
],
'direction': 'down',
'showactive': True,
}
]
lineplt = lineplt.update_layout(
title_text='Average House Price in UK (£)',
title_x=0.5,
#plot_bgcolor= 'rgb(194, 208, 209)',
xaxis_showgrid=False,
yaxis_showgrid=False,
hoverlabel=dict(font_size=10, bgcolor='rgb(69, 95, 154)',
bordercolor= 'whitesmoke'),
legend=dict(title='Please click legend item to remove <br>or add to plot',
x=0,
y=1,
traceorder='normal',
bgcolor='LightSteelBlue',
xanchor = 'auto'),
updatemenus=updatemenus
)
lineplt = lineplt.update_traces(mode="lines", hovertemplate= 'Date = %{x} <br>' + 'Price = £%{y:.2f}')
lineplt.show()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With