首页 > 解决方案 > 创建下拉按钮以根据分类列进行过滤

问题描述

我有一个这样的数据框:

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) 和 2 ys ( col1and col2) 的情节图。就像这个,类别下拉按钮让您选择类别并通过过滤所选类别的数据来col1更新图形。col2

在此处输入图像描述

但是我无法使下拉菜单起作用并更新行。

这是我试过的代码:

# 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)将过滤该数据并为该选定类别绘制x和。ys

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

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

标签: pythonplotly

解决方案


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]))

请注意,现在您甚至不需要导入offline,因为图形本身就是一个 ipython 小部件。Plotly 3 还实现了一种命令式的方式来编写我认为非常有用的代码,你可以在这篇文章中阅读更多关于这个和其他 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]))

推荐阅读