Creating dropdown with multiple options in loop

Hi @empet. Thanks for continuing to take the time to reply. This still isn’t quite what I am trying to accomplish. The example you provided has two dropdowns that are independent of the other.

I will provide the data I am working with to try and help better explain.

I have two dictionaries, each with 4 keys. One dictionary, df_vals, represents the actual data over a specified time. The second dictionary, df_deltas, represents the change of those values in the last 24 hours. The data is updated every 24 hours with the latest and great data.

df_vals.keys()
dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])

df_deltas.keys()
dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])

Here is what the first key looks like for both:

df_vals['corn'].head()
time	2m_temp_prod	2m_temp_area	total_precip_prod	total_precip_area
0	2020-08-29 00:00:00	299.346777	299.799234	0.000000	0.000000
1	2020-08-29 06:00:00	294.039512	294.443352	0.191070	0.286952
2	2020-08-29 12:00:00	292.959274	293.182931	0.155765	0.216606
3	2020-08-29 18:00:00	301.318046	301.767516	0.421768	0.485691
4	2020-08-30 00:00:00	300.623567	300.979650	0.363572	0.501164
df_deltas['corn'].head()
time	2m_temp_24hdelta_prod	2m_temp_24hdelta_area	total_precip_24hdelta_prod	total_precip_24hdelta_area
0	2020-08-29	-0.330566	-0.294223	-1.441738	-0.896948
1	2020-08-30	-0.063527	-0.066953	-3.242770	-2.002193
2	2020-08-31	-0.276225	-0.238248	-1.954929	-1.326568
3	2020-09-01	-0.778811	-0.747444	1.080549	0.523297
4	2020-09-02	-0.121823	-0.008793	-2.857210	-1.974432

So we can see that we have two variables in each dictionary key that we want to plot. Temperature and precipitation. For this example, let’s focus on the columns that end in ā€˜prod’.

df_vals['corn']['time']
0    2020-08-29 00:00:00
1    2020-08-29 06:00:00
2    2020-08-29 12:00:00
3    2020-08-29 18:00:00
4    2020-08-30 00:00:00
             ...        
56   2020-09-12 00:00:00
57   2020-09-12 06:00:00
58   2020-09-12 12:00:00
59   2020-09-12 18:00:00
60   2020-09-13 00:00:00
Name: time, Length: 61, dtype: datetime64[ns]

df_deltas['corn']['time']
0    2020-08-29
1    2020-08-30
2    2020-08-31
3    2020-09-01
4    2020-09-02
5    2020-09-03
6    2020-09-04
7    2020-09-05
8    2020-09-06
9    2020-09-07
10   2020-09-08
11   2020-09-09
12   2020-09-10
13   2020-09-11
14   2020-09-12
15   2020-09-13

Now, I want to plot this data using a double y-axis plot, with the actual values as a line and the 24-hour changes as a bar. I can do that like so:

fig = make_subplots(specs=[[{"secondary_y": True}]])
fig.add_trace(go.Bar(x=df_deltas['corn']['time'], y=round((df_deltas['corn']['2m_temp_24hdelta_prod']*(9/5)),2), marker_color='black', opacity=0.6, hovertemplate='Date: %{x|%d %b}<br>Delta: %{y:.2i} F<extra></extra>'),secondary_y=True)
fig.add_trace(go.Scatter(x=df_vals['corn']['time'], y=((df_vals['corn']['2m_temp_prod']-273)*(9/5)+32),mode='lines', line=dict(color='red', width=4), hovertemplate='Date: %{x|%d %b %H%M} UTC<br>Temp: %{y:.2f} F<extra></extra>'))

Great! We have a plot that takes in one entry from one of the dictionary keys, creating a plot like this (the dates are wrong, as this is an older plot):

The precipitation plot looks similar except that it is a cumulative sum of the values over time instead of the instantaneous value at each 6 hour interval.

Now, we want to make it dynamic! Let’s add some dropdowns so the user can change the data around themselves. I understand how to add one dropdown, that isn’t too hard. However, now I want to add a second dropdown. We want the user to be able to select which crop they want to look at (corn, soybeans, winter wheat or spring wheat), but also what variable to plot (temperature or precipitation). As such, we want two dropdowns. The first would have 4 options: corn, soybeans, winter wheat and spring wheat. The second dropdown will have two options: temperature and precipitation.

So if it is set up properly, a user could select ā€˜corn’ from the first dropdown and ā€˜temperatures’ from the second dropdown. As such, the temperature data from the ā€˜corn’ key the dictionary will plot. However, if the user then selects ā€˜soybeans’, while leaving ā€˜temperature’ still selected, the data would also change because the data for ā€˜corn’ and ā€˜soybeans’ are not the same. How would I accomplish this?

Sorry for the novel, but hope this is more clear.

@LOVESN

I didn’t point out that example for its two different plots on which the buttons act, but to suggest that you have the option to perform updates/restyling on a trace and keep the other to the initial settings or don’t apply any update to its the previous state. In a few minutes you decided that my suggestion is not suitable for your case. However this is the solution. Please think at it!

1 Like

very sad you didn’t point out the examples and I wish you will get the nice examples

@empet I really appreciate all of the help you have provided me and hope you can help me figure out this issue. Unfortunately, I cannot figure out how the example you provided can help me attain my goal. I am still stuck, but have approached the problem in a different way now. I will try to summarize below and see if you can help.

I am working with two dictionaries:

df_vals.keys()

dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])

df_deltas.keys()

dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])

Sample of one of the keys:

df_vals['corn'].head()

time	2m_temp_prod	2m_temp_area	total_precip_prod	total_precip_area
0	2020-09-03 00:00:00	299.346777	299.799234	0.000000	0.000000
1	2020-09-03 06:00:00	294.039512	294.443352	0.191070	0.286952
2	2020-09-03 12:00:00	292.959274	293.182931	0.155765	0.216606
3	2020-09-03 18:00:00	301.318046	301.767516	0.421768	0.485691
4	2020-09-04 00:00:00	300.623567	300.979650	0.363572	0.501164 

df_deltas['corn'].head()

time	2m_temp_24hdelta_prod	2m_temp_24hdelta_area	total_precip_24hdelta_prod	total_precip_24hdelta_area
0	2020-09-03	-0.330566	-0.294223	-1.441738	-0.896948
1	2020-09-04	-0.063527	-0.066953	-3.242770	-2.002193
2	2020-09-05	-0.276225	-0.238248	-1.954929	-1.326568
3	2020-09-06	-0.778811	-0.747444	1.080549	0.523297
4	2020-09-07	-0.121823	-0.008793	-2.857210	-1.974432

Now, I go on to make the plot.

fig = make_subplots(specs=[[{"secondary_y": True}]])

time_vals=df_vals['corn']['time']
time_deltas=df_deltas['corn']['time']

temp_prod_vals=df_vals['corn']['2m_temp_prod']
temp_prod_deltas=df_deltas['corn']['2m_temp_24hdelta_prod']


fig.add_trace(go.Scatter(x=time_vals, y=((temp_prod_vals-273)*(9/5)+32),mode='lines', line=dict(color='red', width=4), yaxis='y1', hovertemplate='Date: %{x|%d %b %H%M} UTC<br>Temp: %{y:.2f} F<extra></extra>'),secondary_y=False)
fig.add_trace(go.Bar(x=time_deltas, y=round((temp_prod_deltas*(9/5)),2), marker_color='black', opacity=0.6, yaxis='y2', hovertemplate='Date: %{x|%d %b}<br>Delta: %{y:.2i} F<extra></extra>'),secondary_y=True)


button1= [dict(method= 'update',
                args= [{'y': [((df_vals[i]['2m_temp_prod']-273)*(9/5)+32), round((df_deltas[i]['2m_temp_24hdelta_prod']*(9/5)),2)]}],
                label=i) for i, j in list(zip(df_vals.keys(), df_deltas.keys()))]
button2= [dict(method= 'update',
                args= [{'y': [(df_vals[i]['total_precip_prod'].cumsum())/25.4, round((df_deltas[i]['total_precip_24hdelta_prod']/25.4),2)]}],
                label=i) for i, j in list(zip(df_vals.keys(), df_deltas.keys()))]

fig.update_layout(yaxis2_showgrid=False, title_text='Plot title',showlegend=False,
                  title_x=0.4,
                  width=850,
                  height=450,annotations=
                  [dict(text='Temps:', x=0.02, xref='paper', y=1.12, yref='paper', align='left', showarrow=False),
                  dict(text='Precip:', x=0.36, xref='paper', y=1.12, yref='paper', align='left', showarrow=False)],
                  updatemenus=[dict(active=0,
                                   x=0.1, y=1.18, 
                                   pad={"r": 10, "t": 10},
                                   xanchor='left', 
                                   yanchor='top',
                                   buttons=button1),
                               dict(active=0,
                                   x=0.40, y=1.18, 
                                   pad={"r": 10, "t": 10},
                                   xanchor='left', 
                                   yanchor='top',
                                   buttons=button2)
                              ])

This produces this plot:

This plot is fine and works as intended. However, since both of the dropdown columns have the same name, I think the plot would look more tidy if we combined the similar dropdown options into one button, i.e., button 1 would be (corn, soybeans, winter wheat and spring wheat). Button two then would be the text next to the button (the actual variable we are plotting), temps and precip.

For the life of me I cannot figure out how to code this up, as I have been stuck on this issue for weeks.

Have you had a chance to look at my most recent post? @empet I am still stuck. I will be moving onto trying Bokeh soon if I cannot figure this issue out. Thanks for the help!

I believe I have discovered what I am trying to do is actually impossible in the Python version of Plotly. This would make sense as to why it’s been so difficult. Can you confirm @empet ?