【问题标题】:Plotly: How to create monthly and annual average dropdown options?Plotly:如何创建月平均和年平均下拉选项?
【发布时间】:2021-02-17 05:35:46
【问题描述】:

我希望在 Plotly 中创建一个下拉菜单,以将我原来的每日时间序列切换为月平均值和年平均值。

总的来说,我希望下拉列表中有 3 个选项:一个是绘制的原始每日时间步长,第二个是重新采样的每日月平均数据,第三个是可以从中选择的年度平均值。

这是我目前的所有代码:

import pandas as pd
import numpy as np
from numpy import random
import plotly.express as px
import cufflinks as cf

random.seed(30)

df = pd.DataFrame({
    "Site 1": np.random.rand(366),
    "Site 2": np.random.rand(366),
    "Site 3": np.random.rand(366),
    "Site 4": np.random.rand(366),
    "Site 5": np.random.rand(366),
    "Site 6": np.random.rand(366)})

idx = pd.date_range(start='2000-01-01', end='2000-12-31',freq ='D')
df = df.set_index(idx)

dfmon = df.resample('M').mean()
dfyr = df.resample('AS').mean()

df.index.names = ['Date']
df.reset_index(inplace= True)

dfmon.index.names = ['Date']
dfmon.reset_index(inplace= True)

dfyr.index.names = ['Date']
dfyr.reset_index(inplace= True)

print(df)
dfd_long = dfmon.melt(id_vars='Date',var_name='SiteID', value_name='Values')
dfm_long = dfmon.melt(id_vars='Date',var_name='SiteID', value_name='Values')
dfyr_long = dfyr.melt(id_vars='Date',var_name='SiteID', value_name='Values')

fig = px.line(dfd_long, x=dfd_long['Date'], y="Values", color="SiteID", hover_name="SiteID")

fig.update_layout(updatemenus=list([
    dict(
        buttons=list([   
            dict(
                args=[{'x': [dfm_long.index], 'y': [dfm_long.Values]}],
                label='Monthly',
                method='restyle'
            ),
            dict(
                args=[{'x': [dfyr_long.index], 'y': [dfyr_long.Values]}],
                label='Yearly',
                method='restyle'
            ),
            dict(
                args=[{'x': [dfd_long.index], 'y': [dfd_long.Values]}],
                label='Daily',
                method='restyle'
            )
        ]))]))

fig.show()

关于重新采样到每月和每年的下拉列表,我是否以正确的方式进行?我应该为此使用长数据格式还是宽数据格式?当我使用此代码单击下拉菜单时,它只显示了我期望的 6 行中的一行。我是否需要为每个网站提供一个单独的下拉菜单才能正常工作?

到目前为止,我在 Plotly 方面的经验有限,因此您可以提供的任何帮助或建议都会有很大帮助!

提前感谢您的帮助!

【问题讨论】:

  • Right way? 也许,但不太可能。 Long or wide? 宽。但也许在字典中组织为三个不同的数据框。 Do you need a separate dropdown for each site? 没有。Will my answer solve your challenge? 我希望如此。如果没有,请告诉我。

标签: python python-3.x pandas numpy plotly


【解决方案1】:

下面是一个完整的设置,将为您提供这些选项的以下三个数字:

['daily', 'monthly', 'yearly']

我已将您的设置用于可重现的数据,轻微 扭曲以使数字可以说更有趣。例如,您使用的是"Site 1": np.random.rand(366),而我使用的是np.random.randint(-1, 2, 366).cumsum()。这会产生一个可能显示(随机)趋势而不是噪声的累积序列。这样可以更轻松地查看图中发生的情况 - 尤其是显示每日数据的版本。

情节 1 - 每天

情节 2 - 每月

图 3a - 带有散点跟踪的年度数据

这看起来有点滑稽,你不觉得吗?如果您想将其更改为最后一个选项,请告诉我:

绘图 3b - 带有条形轨迹的年度数据

如果您想了解更多关于完整代码 sn-p 中发生的事情的详细信息(如果 cmets 没有完全涵盖),请告诉我。

import pandas as pd
import numpy as np
from numpy import random
import plotly.express as px
import cufflinks as cf
import plotly.graph_objects as go

random.seed(30)

df = pd.DataFrame({
    "Site 1": np.random.randint(-1, 2, 366).cumsum(),
    "Site 2": np.random.randint(-1, 2, 366).cumsum(),
    "Site 3": np.random.randint(-1, 2, 366).cumsum(),
    "Site 4": np.random.randint(-1, 2, 366).cumsum(),
    "Site 5": np.random.randint(-1, 2, 366).cumsum(),
    "Site 6": np.random.randint(-1, 2, 366).cumsum()})

idx = pd.date_range(start='2000-01-01', end='2000-12-31',freq ='D')
df = df.set_index(idx)

dfmon = df.resample('M').mean()
dfyr = df.resample('AS').mean()

df.index.names = ['Date']
df.reset_index(inplace= True)

dfmon.index.names = ['Date']
dfmon.reset_index(inplace= True)

dfyr.index.names = ['Date']
dfyr.reset_index(inplace= True)

fig = go.Figure()
dfs = {'daily':df, 'monthly': dfmon, 'yearly' :dfyr}

# your setup this far...

# ... here is where I've added my contributions:

# specify visibility for traces accross dataframes
frames = len(dfs) # number of dataframes organized in  dict
columns = len(dfs['daily'].columns) - 1 # number of columns i df, minus 1 for Date
scenarios = [list(s) for s in [e==1 for e in np.eye(frames)]]
visibility = [list(np.repeat(e, columns)) for e in scenarios] 

# container for buttons
buttons = []

# iterate of dataframes in dfs:
# - i is used to reference visibility attributes
# - k is the name for each dataframe
# - v is the dataframe itself
for i, (k, v) in enumerate(dfs.items()):
    print(i)
    for c, column in enumerate(v.columns[1:]):
        fig.add_scatter(name = column,
                        x = v['Date'],
                        y = v[column], 
                        visible=True if k=='daily' else False # 'daily' values are shown from the start
                       )
                
    # one button per dataframe to trigger the visibility
    # of all columns / traces for each dataframe
    button =  dict(label=k,
                   method = 'restyle',
                   args = ['visible',visibility[i]])
    buttons.append(button)

# include dropdown updatemenu in layout
fig.update_layout(updatemenus=[dict(type="dropdown",
                                    direction="down",
                                    buttons = buttons)])
fig.show()

【讨论】:

  • 抱歉耽搁了。这正是我一直在寻找的,并且工作得很好。我没想过将我的数据帧发送到字典,但现在我想起来了,这是有道理的。什么是可见性属性?使用下拉按钮时,它是否只允许在不同的数据帧之间切换?我想我理解其余的代码。感谢您为帮助我解决此问题所付出的努力!
  • @JeffColdplume 在此设置中,您实际上并没有在数据帧之间切换。来自所有数据帧的所有数据都已添加到图中。可见性属性只是确定是否显示特定的一组轨迹。这适用于迹线本身和图例中的符号。如果您想谈谈更多细节,我很乐意通过chat 继续对话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 2021-08-18
相关资源
最近更新 更多