python - 如何使用 updatemenues 优化绘图图?
问题描述
所以,我一直在使用 plotly,最近开始使用 updatemenus 方法来添加按钮。我已经用它创建了几个图表,但我发现很难找到一种有效的方法来更新 updatemenus 部分中的 args 部分。我有一个比示例更大的数据框,但它是相同的想法,所以我有 df:
name unaregate value age
input1 in11 2 0
input1 in11 0 1
input1 in11 2 2
input1 in11 3 3
input1 in11 1 4
input1 in12 1 0
input1 in12 3 1
input1 in12 4 2
input1 in12 2 3
input1 in12 3 4
input1 in13 0 0
input1 in13 2 1
input1 in13 4 2
input1 in13 2 3
input1 in13 3 4
input2 in21 3 0
input2 in21 4 1
input2 in21 2 2
input2 in21 1 3
input2 in21 3 4
input2 in22 4 0
input2 in22 0 1
input2 in22 2 2
input2 in22 4 3
input2 in22 0 4
input2 in23 3 0
input2 in23 4 1
input2 in23 0 2
input2 in23 4 3
input2 in23 2 4
input3 in31 3 0
input3 in31 4 1
input3 in31 2 2
input3 in31 4 3
input3 in31 1 4
input3 in32 4 0
input3 in32 0 1
input3 in32 0 2
input3 in32 2 3
input3 in32 1 4
input3 in33 2 0
input3 in33 3 1
input3 in33 0 2
input3 in33 3 3
input3 in33 4 4
input3 in34 2 0
input3 in34 2 1
input3 in34 3 2
input3 in34 4 3
input3 in34 3 4
这是创建与此类似的数据框的一种超级低效的方法:
df = pd.DataFrame(index=range(5),columns=range(1))
df12 = pd.DataFrame(index=range(5),columns=range(1))
df13 = pd.DataFrame(index=range(5),columns=range(1))
df21 = pd.DataFrame(index=range(5),columns=range(1))
df22 = pd.DataFrame(index=range(5),columns=range(1))
df23 = pd.DataFrame(index=range(5),columns=range(1))
df31 = pd.DataFrame(index=range(5),columns=range(1))
df32 = pd.DataFrame(index=range(5),columns=range(1))
df33 = pd.DataFrame(index=range(5),columns=range(1))
df34 = pd.DataFrame(index=range(5),columns=range(1))
df["name"] = "input1"
df["unaregate"] = "in11"
df["value"] = np.random.randint(0,5, size=len(df))
df["age"] = range(0,len(df))
df12["name"] = "input1"
df12["unaregate"] = "in12"
df12["value"] = np.random.randint(0,5, size=len(df12))
df12["age"] = range(0,len(df12))
df13["name"] = "input1"
df13["unaregate"] = "in13"
df13["value"] = np.random.randint(0,5, size=len(df13))
df13["age"] = range(0,len(df13))
df21["name"] = "input2"
df21["unaregate"] = "in21"
df21["value"] = np.random.randint(0,5, size=len(df21))
df21["age"] = range(0,len(df21))
df22["name"] = "input2"
df22["unaregate"] = "in22"
df22["value"] = np.random.randint(0,5, size=len(df22))
df22["age"] = range(0,len(df22))
df23["name"] = "input2"
df23["unaregate"] = "in23"
df23["value"] = np.random.randint(0,5, size=len(df23))
df23["age"] = range(0,len(df23))
df31["name"] = "input3"
df31["unaregate"] = "in31"
df31["value"] = np.random.randint(0,5, size=len(df31))
df31["age"] = range(0,len(df31))
df32["name"] = "input3"
df32["unaregate"] = "in32"
df32["value"] = np.random.randint(0,5, size=len(df32))
df32["age"] = range(0,len(df32))
df33["name"] = "input3"
df33["unaregate"] = "in33"
df33["value"] = np.random.randint(0,5, size=len(df33))
df33["age"] = range(0,len(df33))
df34["name"] = "input3"
df34["unaregate"] = "in34"
df34["value"] = np.random.randint(0,5, size=len(df34))
df34["age"] = range(0,len(df34))
frames = [df,df12,df13,df21,df22,df23,df31,df32,df33,df34]
df = pd.concat(frames)
df = df.drop([0],axis=1)
这是我为情节采用的方法:
fig = go.Figure()
names = df.name.unique()
for i in names:
db = df[df["name"]==i]
uni = db.unaregate.unique()
for f in uni:
fig.add_trace(go.Scatter(
x=db[db.unaregate==f].age,
y=db[db.unaregate==f].value,
connectgaps=False ,visible=False,
mode='lines', legendgroup=f,name=f))
fig.update_layout(
template="simple_white",
xaxis=dict(title_text="age"),
yaxis=dict(title_text="Value"),
width=1000, height = 600
)
fig.update_layout(
updatemenus=[
dict(
# type="buttons",
# direction="down",
active=0,
# x=0.7,
# y=1.2,
# showactive=True,
buttons=list(
[ dict(
label="Select name",
method="update",
args=[
{"visible": [False,False,False,
False,False,False,
False,False,False,False
]},
],
),
dict(
label="input 1",
method="update",
args=[
{"visible": [True,True,True,
False,False,False,
False,False,False,False
]},
],
),
dict(
label="input 2",
method="update",
args=[
{"visible": [False,False,False,
True,True,True,
False,False,False,False
]},
],
),
dict(
label="input 3",
method="update",
args=[
{"visible": [False,False,False,
False,False,False,
True,True,True,True
]},
],
),
]
),
# showactive=True,
)
]
)
fig
在部分是真假是,有没有办法在循环中添加它们,所以当我有超过五十行时,我不必添加超过 50 个真假?欢迎任何帮助我只想能够为任何类型的类似数据运行此脚本,并且数据的长度无关紧要。
解决方案
- 可以简化数据框的创建。使用带有列表推导的pandas构造函数功能
- 使用plotly express创建图形/轨迹要简单得多
- 核心问题——动态创建可见列表
- 如果跟踪在同名组中,则它是可见的。这里按钮名称对应于跟踪的名称级别
import pandas as pd
import numpy as np
import plotly.express as px
df = (
pd.DataFrame(
[
{
"name": f"input{a}",
"unaregate": f"in{a}{b}",
"value": np.random.randint(0, 5, 5),
}
for a in range(1, 4)
for b in range(1, 4)
]
)
.explode("value")
.pipe(lambda d: d.assign(age=np.random.randint(0, 5, len(d))))
)
# get valid combinations that will create traces
combis = df.groupby(["name","unaregate"]).size().index
# for this example - it's far simpler to use plotly express to create traces
fig = px.line(df, x="age", y="value", color="unaregate").update_traces(visible=False)
# use list comprehesions to populate visible lists
fig.update_layout(
updatemenus=[
{
"active": 0,
"buttons": [
{
"label": "Select name",
"method": "update",
"args": [{"visible": [False for t in fig.data]}],
}
]
+ [
{
"label": n,
"method": "update",
"args": [{"visible": [n == t for t in combis.get_level_values(0)]}],
}
for n in combis.get_level_values(0).unique()
],
}
],
template="simple_white"
)
推荐阅读
- android - Flutter:错误:内部服务器错误,代码 500
- javascript - 在 JavaScript 中将字符串转换为正则表达式
- sql - 插入各种值
- excel - 在 Excel 中复制/粘贴屏幕截图运行时错误 91 vba
- amazon-cloudformation - cloudformation 堆栈使用的 IAM 角色
- android - 从高层次来看,实现从数据库读取锻炼的健身应用程序的最佳方式是什么?
- javascript - 计数器适用于第 1 个帖子,但不适用于第 2 个帖子
- python-3.x - 写出值以在 python 和 lua 脚本之间进行管道传输
- css - 为什么只有某些字体真棒图标通过 css 出现?
- hyperledger-fabric - Hyperledger Composer 如何增加执行超时