Reputation: 13
I am trying to keep the formatting of a Plotly Express Scatterplot for data from the happiness report (2018). I simply want to create a button that can change the x-axis value between certain columns in a pandas dataframe (e.g. "GDP per Capita", "Social Support", etc.)
Here's an example of the scatter plot I am trying to create a button for to switch the X-value of the graph and have it update accordingly.
df = pd.read_csv("https://media.githubusercontent.com/media/ajgallard/happiness_report/main/data/2018_eng.csv")
fig = px.scatter(df,
x="GDP per capita", # The Value I am creating a button for
y="Score",
size="Population",
color="Continent",
hover_name="Country/Region",
size_max=60,
color_discrete_sequence=px.colors.qualitative.G10)
fig.show()
I get the following as a result:
Plotly Express Scatter Plot:
I attempted to implement a solution to a similar question from: Build a plotly scatterplot with two drop down buttons one for x and one for y axis
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
df = pd.read_csv("https://media.githubusercontent.com/media/ajgallard/happiness_report/main/data/2018_eng.csv")
cols = df.columns[2:4].values.tolist() # "GDP per Capita" & "Social Support"
fig = go.Figure()
for col in cols:
figpx = px.scatter(df,
x=col,
y="Score",
size="Population",
color="Continent",
hover_name="Country/Region",
size_max=60,
color_discrete_sequence=px.colors.qualitative.G10).update_traces(visible=False)
fig.add_traces(figpx.data)
fig.update_layout(
updatemenus=[
{
"buttons":
[
{
"label": k,
"method": "update",
"args":
[
{"visible": [k for k in cols]},
],
}
for k in cols
]
}
]
).update_traces(visible=True, selector=0)
fig.show()
Using the above mentioned code I get the following as a result:
Plotly Express with Button Attempt:
What seems to be happening is that the data is overlayed one on top of the other and the button itself does not update anything data related.
I'm fairly new to implementing Plotly Graphs in my data visualizations and I'm open to any other potential workarounds to get the kind of interactive visualization I was hoping to achieve.
Upvotes: 1
Views: 6606
Reputation: 31166
customdata[0][0]
visible
then builds truth list based on value in each traceimport pandas as pd
import plotly.express as px
import plotly.graph_objects as go
df = pd.read_csv("https://media.githubusercontent.com/media/ajgallard/happiness_report/main/data/2018_eng.csv")
cols = df.columns[2:4].values.tolist() # "GDP per Capita" & "Social Support"
fig = go.Figure()
for col in cols:
figpx = px.scatter(df.assign(Plot=col),
x=col,
y="Score",
size="Population",
color="Continent",
hover_name="Country/Region",
hover_data=["Plot"],
size_max=60,
color_discrete_sequence=px.colors.qualitative.G10).update_traces(visible=False)
fig.add_traces(figpx.data)
fig.update_layout(
updatemenus=[
{
"buttons":
[
{
"label": k,
"method": "update",
"args":
[
{"visible": [t.customdata[0][0]==k for t in fig.data]},
],
}
for k in cols
]
}
]
).update_traces(visible=True, selector=lambda t: t.customdata[0][0]==cols[0] )
fig
Upvotes: 2
Reputation: 35155
Following the referenced answer, we need to add an element to be updated: the value of the x-axis and the title. As an additional response, the legend has been changed from duplicate to single. I am quoting @A. Donda answer response.
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
df = pd.read_csv("https://media.githubusercontent.com/media/ajgallard/happiness_report/main/data/2018_eng.csv")
cols = df.columns[2:4].values.tolist() # "GDP per Capita" & "Social Support"
fig = go.Figure()
for col in cols:
figpx = px.scatter(df,
x=col,
y="Score",
size="Population",
color="Continent",
hover_name="Country/Region",
size_max=60,
color_discrete_sequence=px.colors.qualitative.G10).update_traces(visible=False)
fig.add_traces(figpx.data)
fig.update_layout(
updatemenus=[
{
"buttons":
[
{
"label": f'{k}',
"method": "update",
"args":
[
{'x': [df[k]]},
{'xaxis':{'title':k}},
{"visible": k},
],
}
for k in cols
]
}
]
).update_traces(visible=True, selector=0)
names = set()
fig.for_each_trace(
lambda trace:
trace.update(showlegend=False)
if (trace.name in names) else names.add(trace.name))
figpx.data[0]['hovertemplate'] = '<b>%{hovertext}</b><br><br>Continent=Europe<br>GDP per capita=%{x}<br>Score=%{y}<br>Population=%{marker.size}<extra></extra>'
fig.show()
Upvotes: 0