Yas*_*Yas 7 python pandas plotly
我是 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
Run Code Online (Sandbox Code Playgroud)
在这个例子中,如果我选择标签“A”和颜色“红色”,我只想显示标签“A”和颜色“红色”的行的值,如下所示:
num label color value
1 A red 0.4
4 A red 0.6
Run Code Online (Sandbox Code Playgroud)
然后,该图应仅显示 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()
Run Code Online (Sandbox Code Playgroud)
当然可以使用多个下拉菜单来显示和过滤数据框。下面的代码片段将为您做到这一点。该代码段与您提供的代码有很多共同点,但我必须从头开始构建它以确保所有内容协调一致。运行下面的代码片段,然后选择A并Red查看您实际上会得到:
num label color value
1 A red 0.4
4 A red 0.6
Run Code Online (Sandbox Code Playgroud)
图 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},
16: {'num': 17, 'label': 'E', 'color': 'purple', 'value': 0.68}}
).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:
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] into common dimensions
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()
# one trace for each column per dataframe: AI and RANDOM
for col in common_cols:
fig.add_trace(go.Scatter(x=dates,
visible=True,
marker=dict(size=12, line=dict(width=2)),
marker_symbol = 'diamond',name=col
)
)
# menu setup
updatemenu= []
# buttons for menu 1, names
buttons=[]
# create traces for each color:
# build argVals for buttons and create buttons
for df in dfc.keys():
argList = []
for col in dfc[df]:
#print(dfc[df][col].values)
argList.append(dfc[df][col].values)
argVals = [ {'y':argList}]
buttons.append(dict(method='update',
label=df,
visible=True,
args=argVals))
# buttons for menu 2, colors
b2_labels = common_cols
# 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]*len(common_cols)}]})
# 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]*len(common_cols)}]
)
)
# 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]))
# title
fig.update_layout(
title=dict(
text= "<i>Filtering with multiple dropdown buttons</i>",
font={'size':18},
y=0.9,
x=0.5,
xanchor= 'center',
yanchor= 'top'))
# button annotations
fig.update_layout(
annotations=[
dict(text="<i>Label</i>", x=-0.2, xref="paper", y=1.1, yref="paper",
align="left", showarrow=False, font = dict(size=16, color = 'steelblue')),
dict(text="<i>Color</i>", x=-0.2, xref="paper", y=0.7, yref="paper",
align="left", showarrow=False, font = dict(size=16, color = 'steelblue')
)
])
fig.show()
Run Code Online (Sandbox Code Playgroud)