创建下拉按钮以根据分类列进行过滤
我有一个这样的数据框:
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(col1
和 col2
)的绘图图形.像这样,类别下拉按钮让您选择类别并通过过滤所选类别的 col1
和 col2
数据来更新图.
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
(G1
或 G2
) 将过滤该数据并绘制此选定类别的 x
和 ys
.
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.
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]))