创建下拉菜单按钮可基于分类列进行过滤

时间:2019-06-19 15:36:00

标签: python plotly

我有一个这样的数据框:

import pandas as pd
df = pd.DataFrame()
df['category'] = ['G1', 'G1', 'G1', 'G1','G1', 'G1','G1', 'G2', 'G2', 'G2', 'G2', 'G2', 'G2', 'G2']
df['date'] = ['2012-04-01', '2012-04-05', '2012-04-09', '2012-04-11', '2012-04-16', '2012-04-23', '2012-04-30',
          '2012-04-01', '2012-04-05', '2012-04-09', '2012-04-11', '2012-04-16', '2012-04-23', '2012-04-30']
df['col1'] = [54, 34, 65, 67, 23, 34, 54, 23, 67, 24, 64, 24, 45, 89]
df['col2'] = round(df['col1'] * 0.85)

我想创建一个具有1 x(date)和2 ys(col1col2)的图形。像这样,通过类别下拉按钮,您可以选择类别并通过过滤所选类别的col1col2数据来更新图形。

enter image description here

但是我无法使下拉菜单正常工作并更新行。

这是我尝试的代码:

# import plotly
from plotly.offline import init_notebook_mode, iplot, plot
import plotly.graph_objs as go
init_notebook_mode(connected=True)

x  = 'date'
y1 = 'col1'
y2 = 'col2'

trace1 = {
    'x': df[x],
    'y': df[y1],
    'type': 'scatter',
    'mode': 'lines',
    'name':'col 1',
    'marker': {'color': 'blue'}
}

trace2={
    'x': df[x],
    'y': df[y2],
    'type': 'scatter',
    'mode': 'lines',
    'name':'col 2',
    'marker': {'color': 'yellow'}
}

data = [trace1, trace2]

# Create layout for the plot
layout=dict(
    title='my plot',
    xaxis=dict(
        title='Date', 
        type='date', 
        tickformat='%Y-%m-%d', 
        ticklen=5, 
        titlefont=dict(
            family='Old Standard TT, serif',
            size=20,
            color='black'
        )
    ),
    yaxis=dict(
        title='values', 
        ticklen=5,
        titlefont=dict(
            family='Old Standard TT, serif',
            size=20,
            color='black'
            )
        )

    )

# create the empty dropdown menu
updatemenus = list([dict(buttons=list()), 
                    dict(direction='down',
                         showactive=True)])

total_codes = len(df.category.unique()) + 1

for s, categ in enumerate(df.category.unique()):
    visible_traces = [False] * total_codes
    visible_traces[s + 1] = True
    updatemenus[0]['buttons'].append(dict(args=[{'visible': visible_traces}],
                                          label='category',
                                          method='update'))


updatemenus[0]['buttons'].append(dict(args=[{'visible': [True] + [False] *  (total_codes - 1)}],
                                      label='category',
                                      method='update'))
layout['updatemenus'] = updatemenus

fig = dict(data = data, layout = layout)
iplot(fig) 

我想使用category列中的唯一组作为类别下拉按钮,然后选择categoryG1G2)来过滤该数据并绘制出xys用于此所选类别。

我已经查看了位于plotly网站上的下拉页面,但是无法使下拉菜单正常工作。

https://plot.ly/python/dropdowns/

1 个答案:

答案 0 :(得分:1)

Plotly 3实现了ipython widgets本机支持,因此我不确定他们是否正在维护其旧的窗口小部件。我建议使用ipython widgets,因为它们更加标准和灵活,而且即使习惯了一些时间,我也会发现它们更易于使用。这是一个工作示例:

from plotly import graph_objs as go
import ipywidgets as w
from IPython.display import display
import pandas as pd

df = pd.DataFrame()
df['category'] = ['G1', 'G1', 'G1', 'G1','G1', 'G1','G1', 'G2', 'G2', 'G2', 'G2', 'G2', 'G2', 'G2']
df['date'] = ['2012-04-01', '2012-04-05', '2012-04-09', '2012-04-11', '2012-04-16', '2012-04-23', '2012-04-30',
          '2012-04-01', '2012-04-05', '2012-04-09', '2012-04-11', '2012-04-16', '2012-04-23', '2012-04-30']
df['col1'] = [54, 34, 65, 67, 23, 34, 54, 23, 67, 24, 64, 24, 45, 89]
df['col2'] = round(df['col1'] * 0.85)

x  = 'date'
y1 = 'col1'
y2 = 'col2'

trace1 = {
    'x': df[x],
    'y': df[y1],
    'type': 'scatter',
    'mode': 'lines',
    'name':'col 1',
    'marker': {'color': 'blue'}
}

trace2={
    'x': df[x],
    'y': df[y2],
    'type': 'scatter',
    'mode': 'lines',
    'name':'col 2',
    'marker': {'color': 'yellow'}
}

data = [trace1, trace2]

# Create layout for the plot
layout=dict(
    title='my plot',
    xaxis=dict(
        title='Date', 
        type='date', 
        tickformat='%Y-%m-%d', 
        ticklen=5, 
        titlefont=dict(
            family='Old Standard TT, serif',
            size=20,
            color='black'
        )
    ),
    yaxis=dict(
        title='values', 
        ticklen=5,
        titlefont=dict(
            family='Old Standard TT, serif',
            size=20,
            color='black'
            )
        )

    )

# Here's the new part

fig = go.FigureWidget(data=data, layout=layout)

def update_fig(change):
    aux_df = df[df.category.isin(change['new'])]
    with fig.batch_update():
        for trace, column in zip(fig.data, [y1, y2]):
            trace.x = aux_df[x]
            trace.y = aux_df[column]

drop = w.Dropdown(options=[
    ('All', ['G1', 'G2']),
    ('G1', ['G1']),
    ('G2', ['G2']),
])
drop.observe(update_fig, names='value')

display(w.VBox([drop, fig]))

请注意,由于图形本身是一个ipython小部件,因此您现在甚至不需要导入offline。 Plotly 3还实现了一种强制性的方式来编写我认为非常有用的代码,您可以在this post中阅读有关此功能和其他plotly 3功能的信息(可惜的是文档中并未涉及)。

编辑

对于多个下拉列表,类似的东西应该起作用

def update_fig1(change):
    aux_df = df[df.category == change['new']]
    aux_df = aux_df[aux_df.category1 == drop2.value]
    with fig.batch_update():
        for trace, column in zip(fig.data, [y1, y2]):
            trace.x = aux_df[x]
            trace.y = aux_df[column]

def update_fig2(change):
    aux_df = df[df.category1 == change['new']]
    aux_df = aux_df[aux_df.category == drop1.value]
    with fig.batch_update():
        for trace, column in zip(fig.data, [y1, y2]):
            trace.x = aux_df[x]
            trace.y = aux_df[column]

drop1 = w.Dropdown(options=df.category.unique())
drop2 = w.Dropdown(options=df.category1.unique())

drop1.observe(update_fig1, names='value')
drop2.observe(update_fig2, names='value')

display(w.VBox([w.HBox([drop1, drop2]), fig]))