Plotly Dropdown not updating graphs correctly - pandas

I am working on creating dropdown menu for my data
here is my data
data = {'Time': [2,4,5,6,7], 'Voltage': [20.3, 17.2,15.3,9.4,2], "Current":[2, 5,7,8,9]}
df = pd.DataFrame(data)
this is the code for plotting dropdowns
plot = px.Figure(data=[go.Scatter(
name='Voltage',
x=df["Time"],
y=df["Voltage"]
),
go.Scatter(
name='Data 2',
x=df["Time"],
y=df["Current"]
)
])
plot.update_layout(
updatemenus=[
dict(
buttons=list([
dict(label="Voltage",
method="update",
args=[{"visible": [True, False]},
{"title": "Voltage",
}]),
dict(label="Current",
method="update",
args=[{"visible": [False, True]},
{"title": "Data 2",
}]),
]),
)
])
plot.show()
even though i am not selecting both plots to display it is showing both plots how to overcome this
thanks and regards

You need to add visible = Falseto second scatter. So it should be :
go.Scatter(
name='Data 2',
x=df["Time"],
y=df["Current"] ,
visible = False)

Your code defines the two scatter plots as one graph, so if you rewrite it to set up two graphs, the buttons are not set up incorrectly and the graph can be changed by the drop down buttons.
import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(name='Voltage', x=df["Time"], y=df["Voltage"], line_color='blue'))
fig.add_trace(go.Scatter(name='Data 2', x=df["Time"], y=df["Current"], line_color='red'))
fig.update_layout(
updatemenus=[
dict(
buttons=list([
dict(label="Voltage",
method="update",
args=[{"visible": [True, False]},
{"title": "Voltage",
}]),
dict(label="Current",
method="update",
args=[{"visible": [False, True]},
{"title": "Data 2",
}]),
]),
)
])
fig.show()

Related

Manipulating the legend for a Seaborn Jointplot

I am seeking advice on how to edit the colors of the symbols in my legend when using a seaborn jointplot with several other matplotlib scatterplot layers.
My Specific Question:
Given the data and the current chart below, how can make an adjustment to the code so that the colors of the latter five points on the legend (e.g., "3", "4", "5", "6", "8") can be changed to gray (i.e., #b9b9bd)?
The reproducible code has been pasted below, but there is a publicly accessible Colab Notebook that can be copied and used for experimentation.
Reproducible Example
# import pacakges
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
# load the mpg dataset
mpg_df = sns.load_dataset("mpg")
mpg_df = (
mpg_df
.astype({"cylinders":"category"})
)
mpg_df["cylinders"] = (
mpg_df["cylinders"]
.cat
.as_ordered()
)
# establish the markers
_markers_cylinders = {
3:"P",
4:"d",
5:"v",
6:"X",
8:"s"
}
# establish colors for countries
_palette_origin = {
"usa":"#fca847",
"japan":"#8aed7b",
"europe":"#7b81ed"
}
kws={
"s": 225,
"linewidth": 2
}
# plot the jointplot -- establish the figure -- the content of the plot is not needed just the marginal ditributions
jp = sns.jointplot(
data=mpg_df,
x="weight",
y="mpg",
hue="origin",
palette=_palette_origin,
markers=",",
marginal_kws={"fill":True},
color="w",
height=10,
s=1
)
# plot scatter by origin and cylinder as layers on the original jointplot
origin = ["usa", "japan", "europe"]
for nation in origin:
df = mpg_df[mpg_df["origin"] == nation]
for k,v in _markers_cylinders.items():
jp.ax_joint.scatter(
data=df[df["cylinders"]==k],
x="weight",
y="mpg",
marker=_markers_cylinders[k],
c=_palette_origin[nation],
edgecolor="k",
alpha=0.6,
**kws
)
jp.ax_joint.grid(
color="k",
linestyle=":",
linewidth=0.75
)
han, lab = jp.ax_joint.get_legend_handles_labels()
lab = [
"USA",
"Japan",
"Europe",
"3",
"4",
"5",
"6",
"8"
]
jp.ax_joint.legend(
han[0:8],
lab[0:8],
title="Origin & Cylinders",
fontsize=15,
bbox_to_anchor=(1.20, 1),
title_fontsize = 14,
markerscale=2.5,
shadow = True
)
sns.move_legend(
jp.ax_joint,
loc="upper left",
bbox_to_anchor=(1.20, 1),
markerscale=0.25
)
plt.show()
plt.show()
This can be accomplished by reusing the existing handles and then changing the face color of the marker.
han, lab = jp.ax_joint.get_legend_handles_labels()
new_han = [
handles[0],
handles[1],
handles[2],
Line2D([0], [0], marker='P', markerfacecolor='#b9b9bd', markeredgecolor='black', markersize=14, ls=''),
Line2D([0], [1], marker='d', markerfacecolor='#b9b9bd', markeredgecolor='black', markersize=14, ls=''),
Line2D([0], [2], marker='v', markerfacecolor='#b9b9bd', markeredgecolor='black', markersize=14, ls=''),
Line2D([0], [3], marker='X', markerfacecolor='#b9b9bd', markeredgecolor='black', markersize=14, ls=''),
Line2D([0], [4], marker='s', markerfacecolor='#b9b9bd', markeredgecolor='black', markersize=14, ls='')
]
jp.ax_joint.legend(
new_han,#han[0:8],
lab[0:8],
title="Origin & Cylinders",
fontsize=15,
bbox_to_anchor=(1.20, 1),
title_fontsize = 14,
markerscale=2.5,
shadow = True
)

Default display of annotations in Plotly/Python using a button

I managed the possibility to switch on and off the annotations in a plotly chart. After the executing the code i would like to see the chart without annotations and if required, the annotations could be activated (Label: OFF).
The following code displays per default the annotations and i am not able to set it up, that the first display of chart will be show without annotations.
import plotly.express as px
import pandas as pd
# assign data of lists.
data = {'x': ["2022-05-06", "2022-05-08", "2022-05-09", "2022-05-12", "2022-05-15", "2022-05-16", "2022-05-22", "2022-05-24", "2022-05-26"],
'y': [0, 1, 8, 2, 4, 3, 4, 6, 5],
'text':["","","Annotation1","","Annotation2","","","","Annotation3"]}
# Create DataFrame
df = pd.DataFrame(data)
# assign data of lists.
data1 = {'x': ["2022-05-07", "2022-05-14", "2022-05-23"],
'text':["Annotation1", "Annotation2", "Annotation3"]}
df1 = pd.DataFrame(data1)
fig = px.line(df, x='x', y='y', title='Annotations ONN / OFF')
arrow_list=[]
counter=0
for i in df1['text'].tolist():
if i != "":
arrow=dict(x=df1['x'].values[counter],y=9,xref="x",yref="y",text=i,arrowhead = 2,ax=0,
arrowwidth=1.5,
bordercolor="#c7c7c7",
borderwidth=2,
borderpad=4,
bgcolor="#ff7f0e",
opacity=0.8,
font=dict(
family="Courier New, monospace",
size=16,
color="#ffffff"
),
arrowcolor='rgb(255,51,0)',)
arrow_list.append(arrow)
counter+=1
else:
counter+=1
fig.update_layout(
updatemenus=[
dict(
type="buttons",
# direction="right",
active=0,
showactive=True,
buttons=list([
dict(label="Label:Off",
method="update",
args=[{"visible": [True, False, True, False]},
{"annotations": []}]),
dict(label="Label:On",
method="update",
args=[{"visible": [True, True, True, True]},
{"annotations": arrow_list}]),
]),
)
])
fig.update_layout(annotations=arrow_list)
fig.show()
I have tried to modify args and active, but without any success.
The first display of the charts (annotations should be off):
I found the solution:
import plotly.graph_objects as go
import pandas as pd
# Load dataset
# assign data of lists.
data = {'Date': ["2022-05-06", "2022-05-08", "2022-05-09", "2022-05-12", "2022-05-15", "2022-05-16", "2022-05-22", "2022-05-24", "2022-05-26"],
'High': [0, 1, 8, 2, 4, 3, 4, 6, 5],
'text':["","","Annotation1","","Annotation2","","","","Annotation3"]}
# Create DataFrame
df = pd.DataFrame(data)
# Initialize figure
fig = go.Figure()
# Add Traces
fig.add_trace(
go.Scatter(x=list(df.Date),
y=list(df.High),
name="High",
line=dict(color="#33CFA5")))
arrow_list=[]
counter=0
for i in df1['text'].tolist():
if i != "":
arrow=dict(x=df1['x'].values[counter],y=9,xref="x",yref="y",text=i,arrowhead = 2,ax=0,
arrowwidth=1.5,
bordercolor="#c7c7c7",
borderwidth=2,
borderpad=4,
bgcolor="#ff7f0e",
opacity=0.8,
font=dict(
family="Courier New, monospace",
size=16,
color="#ffffff"
),
arrowcolor='rgb(255,51,0)',)
arrow_list.append(arrow)
counter+=1
else:
counter+=1
fig.update_layout(
updatemenus=[
dict(
active=0,
buttons=list([
dict(label="Label: Off",
method="update",
args=[{"visible": [True, False, True, False]},
{"title": "Labels Off",
"annotations": []}]),
dict(label="Label: On",
method="update",
args=[{"visible": [True, True, False, False]},
{"title": "Labels On",
"annotations": arrow_list}]),
]),
)
])
fig.show()

Convert pandas dataframe to datasetDict

I cannot find anywhere how to convert a pandas dataframe to type datasets.dataset_dict.DatasetDict, for optimal use in a BERT workflow with a huggingface model. Take these simple dataframes, for example.
train_df = pd.DataFrame({
"label" : [1, 2, 3],
"text" : ["apple", "pear", "strawberry"]
})
test_df = pd.DataFrame({
"label" : [2, 2, 1],
"text" : ["banana", "pear", "apple"]
})
What is the most efficient way to convert these to the type above?
One possibility is to first create two Datasets and then join them:
import datasets
import pandas as pd
train_df = pd.DataFrame({
"label" : [1, 2, 3],
"text" : ["apple", "pear", "strawberry"]
})
test_df = pd.DataFrame({
"label" : [2, 2, 1],
"text" : ["banana", "pear", "apple"]
})
train_dataset = Dataset.from_dict(train_df)
test_dataset = Dataset.from_dict(test_df)
my_dataset_dict = datasets.DatasetDict({"train":train_dataset,"test":test_dataset})
The result is:
DatasetDict({
train: Dataset({
features: ['label', 'text'],
num_rows: 3
})
test: Dataset({
features: ['label', 'text'],
num_rows: 3
})
})

Stacked Bar-chart based on bool value column Altair

I'm trying to do something like below.
Group by the date column, for example year or year/month.
And visualize a stacked bar chart, based on the True/False value.
What's the best way to go about this in Altair?
df = pd.DataFrame({
'date': ['20-03-2017', '20-03-2017', '20-03-2018', '21-03-2018', '20-10-2019', '20-03-2019', '1-02-2019', '10-03-2020', '20-06-2020'],
'value': [True, True, True, False, True, False, False, True, False]
})
import altair as alt
alt.Chart(df).mark_bar().encode(
x = 'groupbyyear(date)',
y = 'count(value)',
color = 'value'
)
You're very close: instead of groupbyyear you can use a year time unit transform, and since your dates are non-standard format, you can first use pandas to_datetime to convert them to standard date values. The result looks like this:
import altair as alt
import pandas as pd
df = pd.DataFrame({
'date': ['20-03-2017', '20-03-2017', '20-03-2018', '21-03-2018', '20-10-2019', '20-03-2019', '1-02-2019', '10-03-2020', '20-06-2020'],
'value': [True, True, True, False, True, False, False, True, False]
})
df['date'] = pd.to_datetime(df['date'])
alt.Chart(df).mark_bar().encode(
x = 'year(date):O',
y = 'count(value)',
color = 'value'
)

Return a graph based on a value from the dropdown

I am trying to plot a matplotlib graph after based on the value chosen from the dropdown. I have made the dropdown and the plots are also ready for the values but i dont know how to connect both of them together.
Following is the code of the dropdown:
app.layout = html.Div([
dcc.Dropdown(
id='first-dropdown',
options = [
{'label': 'Chest Pain', 'value': 'cp'},
{'label': 'Resting Blood Pressure', 'value': 'trestbps'},
{'label': 'Serum Cholestrol in mg/dl', 'value': 'chol'},
{'label': 'Fasting Blood Pressure', 'value': 'fbs'},
{'label': 'Resting electrocardiographic results', 'value': 'restecg'},
{'label': 'Maximum heart rate achieved', 'value': 'thalach'},
{'label': 'Exercise induced angina', 'value': 'exang'},
{'label': 'Old Peak', 'value': 'oldpeak'},
{'label': 'Slope of the peak exercise ST segment', 'value': 'slope'},
{'label': 'Number of major vessels (0-3) colored by flourosopy', 'value': 'ca'},
{'label': 'Thalassemia', 'value': 'thal'}
],
value= 'thalach'
)
])
and for each value in the dropdown i have a separate function which returns a plot. For eg:
What i am trying to do is that if the Label 'Max Heart Rate Achieved' is selected from the dropdown whose value is 'thalach'. I have a function called plotThalach which returns a plot like this:
def plotThalach(df):
df_men = df[df['sex'] == 1.0]
df_women = df[df['sex'] == 0.0]
plt.figure(figsize=(20, 8))
plt.bar(df_men['age'] + 0.00, df_men['thalach'], color='b', width=0.25, label='Men')
plt.bar(df_women['age'] + 0.25, df_women['thalach'], color='r', width=0.25, label='Women')
plt.legend(loc='upper right')
plt.xlabel("Age")
plt.ylabel("Max Heart Rate")
plt.title("Age vs Max Heart Rate")
return plt
Now how do i connect both of these in such a way that when a value is selected from the dropdown my function gets called and plot gets displayed on the screen.
It's not so clear why you want to mix plotly-dash and matplotlib, you can easily do it using just plotly-dash
Here is a sample code,
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
df = pd.read_csv(
'https://raw.githubusercontent.com/plotly/'
'datasets/master/gapminderDataFiveYear.csv')
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
#main div
app.layout = html.Div([
#drop down with a default value set
dcc.Dropdown(
id='xaxis-column',
options=[{'label': str(year), 'value': year} for year in df['year'].unique()],
value=df['year'].min(),
),
#graph that is to be updated
dcc.Graph(id='graph-with-slider')
])
#callback which will be spawned when the input changes, in this case the input is the dropdown value
#app.callback(
Output('graph-with-slider', 'figure'),
[Input('xaxis-column', 'value')])
def update_figure(selected_year):
filtered_df = df[df.year == selected_year]
traces = []
for i in filtered_df.continent.unique():
df_by_continent = filtered_df[filtered_df['continent'] == i]
traces.append(go.Scatter(
x=df_by_continent['gdpPercap'],
y=df_by_continent['lifeExp'],
text=df_by_continent['country'],
mode='markers',
opacity=0.7,
marker={
'size': 15,
'line': {'width': 0.5, 'color': 'white'}
},
name=i
))
return {
'data': traces,
'layout': go.Layout(
xaxis={'type': 'log', 'title': 'GDP Per Capita'},
yaxis={'title': 'Life Expectancy', 'range': [20, 90]},
margin={'l': 40, 'b': 40, 't': 10, 'r': 10},
legend={'x': 0, 'y': 1},
hovermode='closest'
)
}
if __name__ == '__main__':
app.run_server(debug=True)
But if you want to show the matplotlib graph instead of plotly-dash graph, you can refer the "Incorporating Matplotlib Plots" section here