Python 有计划地组织下拉菜单

Python 有计划地组织下拉菜单,python,pandas,plotly,Python,Pandas,Plotly,我正在使用两本字典,每本字典有4个键。两本词典中的键相同,对应于美国的作物带 df_vals.keys() dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat']) df_deltas.keys() dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat']) 在每个键中都有一个包含5列的数据帧,其中第一列是时间,其他列是各种变量。例如: df_vals['corn

我正在使用两本字典,每本字典有4个键。两本词典中的键相同,对应于美国的作物带

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

df_deltas.keys()
dict_keys(['corn', 'soybeans', 'winterwheat', 'springwheat'])
在每个键中都有一个包含5列的数据帧,其中第一列是时间,其他列是各种变量。例如:

df_vals['corn'].head()
time    2m_temp_prod    2m_temp_area    total_precip_prod   total_precip_area
0   2020-09-17 00:00:00 299.346777  299.799234  0.000000    0.000000
1   2020-09-17 06:00:00 294.039512  294.443352  0.191070    0.286952
2   2020-09-17 12:00:00 292.959274  293.182931  0.155765    0.216606
3   2020-09-17 18:00:00 301.318046  301.767516  0.421768    0.485691
4   2020-09-18 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-17  -0.330566   -0.294223   -1.441738   -0.896948
1   2020-09-18  -0.063527   -0.066953   -3.242770   -2.002193
2   2020-09-19  -0.276225   -0.238248   -1.954929   -1.326568
3   2020-09-20  -0.778811   -0.747444   1.080549    0.523297
4   2020-09-21  -0.121823   -0.008793   -2.857210   -1.974432
请注意,
df_vals
为6小时,
df_delta
为24小时。现在,我想用双y轴绘制一个图,
df_vals
中的一个变量被绘制为直线,
df_delta
中相应的变量被绘制为条形图。这很容易做到,也可以做到,如下所示:

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)
很好,现在我们有了一个通过每个dict键的绘图,并根据您选择的作物进行更新

现在,如果我们想在一个特定的数据帧中循环其他列(变量),该怎么办?到目前为止,我们只绘制了温度图。让我们现在绘制降水图。我们需要添加第二个按钮来执行此操作:

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.title()) for i, j in list(zip(df_vals.keys(), df_deltas.keys()))]
这个按钮现在看起来和我们的第一个按钮一模一样,每个下拉选项都是dicts中的一个键。完成的绘图如下所示:

该图按预期工作,但有点笨重,因为我们有两个下拉菜单,具有相同的精确选项。现在我们已经达到了这篇文章的目的。我们绘制的变量(温度和精度)没有两个按钮,而是一个按钮用于作物带,一个按钮用于变量。然而,我似乎不知道如何调整代码的方向来实现这一点。任何帮助都将不胜感激

编辑:

其他3个键(大豆、冬小麦和春小麦)都具有与此相同的结构,只是值不同

编辑3: 发布完整的代码和库

import xarray as xr
import glob
import datetime as dt
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
我使用xarray加载了几个不同的netcdf时间序列文件。这些文件是预测模型数据,从模型运行之日起15天内运行。还有delta文件,它告诉您预测变量在24小时前的变化(因此它们只在14天内发出)

这会将所有文件加载到字典中,每个键表示预测变量的作物。每个时间序列以每小时6次的格式设置。但是,我想进一步调整它,因为我需要增量的时间是24小时,而不是6小时

today=dt.date.today()
df_vals={}
df_deltas={}
for i in data.keys():
    df_vals[str(i)]=data[i].to_dataframe().reset_index()
    df_vals[i]['time']=pd.date_range((today-dt.timedelta(days=5)), (today+dt.timedelta(days=10)), freq='6H')
    
    df_deltas[i]=df_vals[i].filter(regex='delta')
    df_deltas[i]['time']=pd.date_range((today-dt.timedelta(days=5)), (today+dt.timedelta(days=10)), freq='6H')
    df_deltas[i]=df_deltas[i].set_index('time')
    
    cols = [c for c in df_deltas[i].columns if "precip" in c or "temp" in c]
    aggs = {c:'sum' if 'precip' in c else 'mean' for c in cols}
    df_deltas[i]=df_deltas[i].resample('24h').agg(aggs)
    
    df_deltas[i]=df_deltas[i].reset_index().fillna(0)
    
    df_vals[i]=df_vals[i][df_vals[i].columns.drop(list(df_vals[i].filter(regex='delta')))].fillna(value=0)

for i in df_vals.keys():
    df_vals[i]=df_vals[i].drop(['snowfall_prod', 'snowfall_area'], 1)
现在我已经达到了我想要的。两个字典,包含4个键(代表4种作物),以6小时时间分辨率显示
df_vals
,以24小时时间分辨率显示
df_delta
。然后,我策划

图=生成子图(规格=[{“次要”:True}]]

time\u vals=df\u vals['corn']['time']
时间增量=df增量['corn']['time']
生产温度=生产温度[“玉米”][“2米生产温度”]
temp_prod_delta=df_delta['corn']['2m_temp_24hdelta_prod']
图添加跟踪(go.Scatter(x=时间,y=((临时生产日期-273)*(9/5)+32),模式='lines',line=dict(颜色='红色',宽度=4),yaxis='y1',hovertemplate='Date:%{x |%d%b%H%M}UTC
温度:%{y:.2f}'F',secondary'y=False) 图2.add_trace(go.Bar(x=时间增量,y=圆形((临时生产增量*(9/5)),2),marker_color='黑色',不透明度=0.6,yaxis='y2',hovertemplate='Date:%{x|d%b}
增量:%{y:.2i}F'),次要_y=True) button1=[dict(方法='update', args=[{'y':[((df_vals[i]['2m临时生产]-273)*(9/5)+32),圆形((df_delta[i]['2m临时生产]*(9/5)),2)], label=i.title())表示列表中的i,j(zip(df_vals.keys(),df_delta.keys())] button2=[dict(方法='update', args=[{'y':[(df_vals[i]['total_precip_prod'].cumsum())/25.4,圆形((df_delta[i]['total_precip_24hdelta_prod']/25.4),2)], label=i.title())表示列表中的i,j(zip(df_vals.keys(),df_delta.keys())] 图更新布局(yaxis2\u showgrid=False,title\u text='Plot title',showlegend=False, 标题x=0.4, 宽度=850, 高度=450,注释= [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(活动=0, x=0.1,y=1.18, pad={r:10,“t:10}, xanchor='left', yanchor='top', 按钮=按钮1), dict(活动=0, x=0.40,y=1.18, pad={r:10,“t:10}, xanchor='left', yanchor='top', 按钮=按钮2) ])
在我看来,这里你应该使用dash,尤其是@Elitaruasky,你不必学习JS。但你应该学一点Dash。在情节上,Dash和Python是一个奇妙的组合@维斯特兰:我当然应该。哈哈。我想我真的要花点时间来学习Dash,因为它似乎应该能够完成这个任务和我心目中的其他类似任务。谢谢你的邀请suggestions@EliTurasky如果你花时间分享你的数据集,当我找到时间的时候,我会仔细看看。@EliTurasky,我明白了。嗯,我可能会那样做。最终。但请记住,任何人花在复制你的问题上的每一分钟都比回答你的问题少了一分钟。在我看来,你应该使用dash,尤其是@Elitaruasky,你不必学习JS。但你应该学一点Dash。在情节上,Dash和Python是一个奇妙的组合@维斯特兰:我当然应该。哈哈。我想我真的要花点时间来学习Dash,因为它似乎应该能够完成这个任务和我心目中的其他类似任务。谢谢你的建议
import xarray as xr
import glob
import datetime as dt
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
corn=glob.glob('/Users/eli.turaskyriskpulse.com/Documents/Python_data/plotly_practice/20200812_00/20200812_00_ec_ens_*'+'corn'+'_timeseries.nc')
soybean=glob.glob('/Users/eli.turaskyriskpulse.com/Documents/Python_data/plotly_practice/20200812_00/20200812_00_ec_ens_*'+'soybeans'+'_timeseries.nc')
winterwheat=glob.glob('/Users/eli.turaskyriskpulse.com/Documents/Python_data/plotly_practice/20200812_00/20200812_00_ec_ens_*'+'winterwheat'+'_timeseries.nc')
springwheat=glob.glob('/Users/eli.turaskyriskpulse.com/Documents/Python_data/plotly_practice/20200812_00/20200812_00_ec_ens_*'+'springwheat'+'_timeseries.nc')
all_files=[corn, soybean,winterwheat,springwheat]

crop_names=['corn', 'soybeans', 'winterwheat', 'springwheat']
data={}
for i in all_files:
    data[str(i)]=xr.open_mfdataset(i).load()
today=dt.date.today()
df_vals={}
df_deltas={}
for i in data.keys():
    df_vals[str(i)]=data[i].to_dataframe().reset_index()
    df_vals[i]['time']=pd.date_range((today-dt.timedelta(days=5)), (today+dt.timedelta(days=10)), freq='6H')
    
    df_deltas[i]=df_vals[i].filter(regex='delta')
    df_deltas[i]['time']=pd.date_range((today-dt.timedelta(days=5)), (today+dt.timedelta(days=10)), freq='6H')
    df_deltas[i]=df_deltas[i].set_index('time')
    
    cols = [c for c in df_deltas[i].columns if "precip" in c or "temp" in c]
    aggs = {c:'sum' if 'precip' in c else 'mean' for c in cols}
    df_deltas[i]=df_deltas[i].resample('24h').agg(aggs)
    
    df_deltas[i]=df_deltas[i].reset_index().fillna(0)
    
    df_vals[i]=df_vals[i][df_vals[i].columns.drop(list(df_vals[i].filter(regex='delta')))].fillna(value=0)

for i in df_vals.keys():
    df_vals[i]=df_vals[i].drop(['snowfall_prod', 'snowfall_area'], 1)
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.title()) 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.title()) 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)
                              ])