创建下拉按钮以根据分类列进行过滤 [英] Create dropdown button to filter based on a categorical column

查看:40
本文介绍了创建下拉按钮以根据分类列进行过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个这样的数据框:

I have a dataframe like this:

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 数据来更新图.

I want to create a plotly figure that has one x (date) and 2 ys (col1 and col2). like this one, where the category dropdown button let's you select the category and updates the figure by filtering the col1 and col2 data for the selected category.

但我无法使下拉菜单工作并更新行.

But I cannot make the dropdown to work and update the lines.

这是我试过的代码:

# 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 列中的唯一组创建类别下拉按钮,然后选择 category(G1G2) 将过滤该数据并绘制此选定类别的 xys.

I want make the category dropdown button with unique groups from category column, and selecting the category (either G1 or G2) will filter that data and plot the x and ys for this selected category.

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

I already looked at dropdown page on plotly website but couldn't make the dropdown to work.

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

推荐答案

Plotly 3 实现了 ipython 小部件 原生支持,我不确定他们是否在维护旧的小部件.我建议使用 ipython 小部件,因为它们更标准和灵活,而且我发现它们更容易使用,即使需要一些时间来习惯它们.这是一个工作示例:

Plotly 3 implemented ipython widgets native support, with this I'm not sure they are maintaining their old widgets. I suggest using ipython widgets because they are more standard and flexible, also I find them a bit easier to use even when it takes some time to get used to them. Here's a working example:

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 还实现了一种编写我认为非常有用的代码的命令式方法,您可以在 这篇文章.

note that now you don't even need to import offline as the figure itself is an ipython widget. Plotly 3 also implemented an imperative way to write the code that I find to be really useful, you can read more about this and other plotly 3 features (that are sadly not really covered on the docs) in this post.

编辑

对于不止一个下拉菜单,这样的操作应该可以

for more than one dropdown something like this should work

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

这篇关于创建下拉按钮以根据分类列进行过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆