我是Python,Pandas和Plotly的新手,所以也许答案很简单,但我在论坛或其他任何地方都找不到任何东西……
我不想使用Dash或ipywidgets,因为我希望能够使用plotly.offline.plot以HTML格式导出(我需要一个交互式HTML文件来动态控制图形,而没有任何服务器像Dash一样运行) 。
我的问题是,我想使用几个(累积的)下拉按钮(在此示例中为2个,但可能会更多)来过滤一个绘图图形,方法是使用下拉菜单中的选定值过滤原始数据列表。
num label color value
1 A red 0.4
2 A blue 0.2
3 A green 0.3
4 A red 0.6
5 A blue 0.7
6 A green 0.4
7 B blue 0.2
8 B green 0.4
9 B red 0.4
10 B green 0.2
11 C red 0.1
12 C blue 0.3
13 D red 0.8
14 D blue 0.4
15 D green 0.6
16 D yellow 0.5
在此示例中,如果我选择标签'A'和颜色'红色',我只显示标签'A'和颜色'红色'的行的值,如下所示:
num label color value
1 A red 0.4
4 A red 0.6
然后,图形应仅显示2个值
1)这是我目前拥有的代码(请参见下文),但我不知道如何继续。你有什么主意吗?
2)额外的问题:是否可以使用复选框而不是下拉列表,以便能够在条件内选择多个值,例如:标签过滤器可以是A或B,而不是列表中的一个…
感谢您的帮助!
import pandas as pd
import plotly.graph_objects as go
d = {
'num' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
'label' : ['A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'D', 'D', 'D', 'D'],
'color' : ['red', 'blue', 'green', 'red', 'blue', 'green', 'blue', 'green', 'red', 'green', 'red', 'blue', 'red', 'blue', 'green', 'yellow'],
'value' : [0.4, 0.2, 0.3, 0.6, 0.7, 0.4, 0.2, 0.4, 0.4, 0.2, 0.1, 0.3, 0.8, 0.4, 0.6, 0.5]
}
# Build dataframe
df = pd.DataFrame(data=d)
# Build dropdown Labels
labels = df["label"].unique()
buttonsLabels = [dict(label = "All labels",
method = "restyle",
args = [{'y' : [df["value"] * 100]}] # or what else ?
)]
for label in labels:
buttonsLabels.append(dict(label = label,
method = "restyle",
visible = True,
#args = [{'y' : ??? }]
))
# Build dropdown Colors
colors = df["color"].unique()
buttonsColors = [dict(label = "All colors",
method = "restyle",
args = [{'y' : [df["value"] * 100]}] # or what else ?
)]
for color in colors:
buttonsColors.append(dict(label = color,
method = "restyle",
visible = True,
# args = [{'y' : ??? }]
))
# Display figure
fig = go.Figure(data = [ go.Scatter(x = df["num"], y = df["value"] * 100 ) ])
fig.update_layout(updatemenus = [
dict(buttons = buttonsLabels, showactive = True),
dict(buttons = buttonsColors, showactive = True, y = 0.8)
])
fig.show()
是的,当然可以显示和过滤具有多个下拉菜单的数据框。下面的代码段将为您完成此操作。该代码段与您提供的代码中包含的元素很少,但是我必须从头开始构建它,以确保所有内容协调一致。运行以下代码段,然后依次选择A
和Red
,您实际上会得到:
num label color value
1 A red 0.4
4 A red 0.6
图1:标签= A,颜色=红色
这是另一个选择的相同情节:
图2:标签= B,颜色=全部
完整代码:
# Imports
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# source data
df = pd.DataFrame({0: {'num': 1, 'label': 'A', 'color': 'red', 'value': 0.4},
1: {'num': 2, 'label': 'A', 'color': 'blue', 'value': 0.2},
2: {'num': 3, 'label': 'A', 'color': 'green', 'value': 0.3},
3: {'num': 4, 'label': 'A', 'color': 'red', 'value': 0.6},
4: {'num': 5, 'label': 'A', 'color': 'blue', 'value': 0.7},
5: {'num': 6, 'label': 'A', 'color': 'green', 'value': 0.4},
6: {'num': 7, 'label': 'B', 'color': 'blue', 'value': 0.2},
7: {'num': 8, 'label': 'B', 'color': 'green', 'value': 0.4},
8: {'num': 9, 'label': 'B', 'color': 'red', 'value': 0.4},
9: {'num': 10, 'label': 'B', 'color': 'green', 'value': 0.2},
10: {'num': 11, 'label': 'C', 'color': 'red', 'value': 0.1},
11: {'num': 12, 'label': 'C', 'color': 'blue', 'value': 0.3},
12: {'num': 13, 'label': 'D', 'color': 'red', 'value': 0.8},
13: {'num': 14, 'label': 'D', 'color': 'blue', 'value': 0.4},
14: {'num': 15, 'label': 'D', 'color': 'green', 'value': 0.6},
15: {'num': 16, 'label': 'D', 'color': 'yellow', 'value': 0.5}}).T
df_input = df.copy()
# split df by labels
labels = df['label'].unique().tolist()
dates = df['num'].unique().tolist()
# dataframe collection grouped by labels
dfs = {}
for label in labels:
#print(label)
dfs[label]=pd.pivot_table(df[df['label']==label],
values='value',
index=['num'],
columns=['color'],
aggfunc=np.sum)
# find row and column unions
common_cols = []
common_rows = []
for df in dfs.keys():
common_cols = sorted(list(set().union(common_cols,list(dfs[df]))))
common_rows = sorted(list(set().union(common_rows,list(dfs[df].index))))
# find dimensionally common dataframe
df_common = pd.DataFrame(np.nan, index=common_rows, columns=common_cols)
# reshape each dfs[df] int common dimension
dfc={}
for df_item in dfs:
#print(dfs[unshaped])
df1 = dfs[df_item].copy()
s=df_common.combine_first(df1)
df_reshaped = df1.reindex_like(s)
dfc[df_item]=df_reshaped
# plotly start
fig = go.Figure()
# get column names from first dataframe in the dict
colNames = list(dfs[list(dfs.keys())[0]].columns)
# one trace for each column per dataframe: AI and RANDOM
for col in colNames:
fig.add_trace(go.Scatter(x=dates,
visible=True,
#name=col
)
)
# menu setup
updatemenu= []
# buttons for menu 1, names
buttons=[]
# create traces for each color:
for df in dfc.keys():
buttons.append(dict(method='update',
label=df,
visible=True,
args=[ {'y':[dfc[df]['blue'].values,
dfc[df]['green'].values,
dfc[df]['red'].values,
dfc[df]['yellow'].values]}]))
# buttons for menu 2, colors
b2_labels = colNames
# matrix to feed all visible arguments for all traces
# so that they can be shown or hidden by choice
b2_show = [list(b) for b in [e==1 for e in np.eye(len(b2_labels))]]
buttons2=[]
buttons2.append({'method': 'update',
'label': 'All',
'args': [{'visible': [True]*4}]})
# create buttons to show or hide
for i in range(0, len(b2_labels)):
buttons2.append(dict(method='update',
label=b2_labels[i],
args=[{'visible':b2_show[i]}]
)
)
# add option for button two to hide all
buttons2.append(dict(method='update',
label='None',
args=[{'visible':[False]*4}]
)
)
# some adjustments to the updatemenus
updatemenu=[]
your_menu=dict()
updatemenu.append(your_menu)
your_menu2=dict()
updatemenu.append(your_menu2)
updatemenu[1]
updatemenu[0]['buttons']=buttons
updatemenu[0]['direction']='down'
updatemenu[0]['showactive']=True
updatemenu[1]['buttons']=buttons2
updatemenu[1]['y']=0.6
fig.update_layout(showlegend=False, updatemenus=updatemenu)
fig.update_layout(yaxis=dict(range=[0,df_input['value'].max()+0.4]))
fig.show()