在这里使用 Python 和 StackOverflow 的 Plotly 新手。我创建了一个图形,其中包含一些箱形图、一个散点图和一些可以中继的元素。
我的数据有差距,我想使用下拉列表选择打开和关闭图表中的显示(见图 1)。
在一种情况下,我可以成功隐藏间隙,但散点图会丢失其 X 轴值并在标记数据结束后绘制(参见图 2)。这是由这行代码产生的:
dict(label="Exclude missing data", method="update", args=[{"x":df.Run[x_some],"visible": x_some}])
在另一种情况下,我可以隐藏数据中的间隙,散点图有效,但“隐藏”的 X 轴标签移动到图表的末尾(见图 3)。这是由这行代码产生的:
dict(label="Exclude missing data", method="update", args=[{"visible": x_some}])
关于我做错了什么以及如何解决这个问题有什么提示吗?
请在下面找到一些示例代码:
import pandas as pd
import numpy as np
import plotly.io as pio
import datetime as dt
import plotly.graph_objects as go
pio.renderers.default = 'browser'
pd.options.plotting.backend = "plotly"
fig = go.Figure()
N = 100
ydata = np.random.randint(600, 1200, size=(100, 5))
x = ["R"+str(i) for i in range(len(ydata))]
df = pd.DataFrame(ydata, columns=["M1", "M2", "M3", "M4", "M5"])
df["X"] = x
gaps = np.r_[20:40, 60:70]
df.iloc[gaps, 0:5] = np.nan
df["Mean"] = df.iloc[:, 0:5].mean(axis=1).round(0)
cols = df.columns.str.contains("M")
# %% figure setup
layout = dict(
height=700, width=1500,
xaxis_title="Run",
xaxis=dict(autorange=False, range=[0, N], type="category"),
yaxis=dict(autorange=True),
font=dict(family="Courier New, monospace", size=12, color="RebeccaPurple"),
showlegend=False
)
fig.layout = layout
mean_line = go.Scatter(x=df.X, y=df.Mean, connectgaps=True, mode='lines+markers', name='Mean line', showlegend=False)
boxes = [go.Box(name=df.X[i], y=df.iloc[i, cols], boxpoints=False, boxmean=True, notched=True, showlegend=False) for i in range(N)]
fig.add_traces(boxes)
x_all = df.index == df.index
x_some = (df.Mean > 0).values
fig.add_trace(mean_line)
fig.update_layout(updatemenus=[
dict(type="dropdown", direction="down", buttons=list([
dict(label="Include missing data", method="update", args=[{"visible": x_all}]),
dict(label="Exclude missing data", method="update", args=[{"visible": x_some}])
]), pad={"l": 10, "t": 10}, showactive=True, x=0.23, xanchor="left", y=1.1, yanchor="top")])
z = fig.to_dict()
fig.show()
发生这种情况的原因是因为您忘记了最后一条痕迹,即散点,它仍然包括
NaN
的 x 值。 (有 100 个框轨迹和 1 个散点轨迹,所以 x_all
和 x_some
实际上应该有长度 101 – 在你的原始代码中,这两个布尔数组的长度为 100,但 plotly 假设你的意思是显示最后一个散点轨迹)
为了解决这个问题,我们可以添加另一个散点图,删除缺失值——我们可以让它默认不可见,只有当您从下拉列表中选择
"Exclude missing data"
时才显示这个散点。
注意:
x_all
和 x_some
现在的长度为 102。x_all
应该看起来像 [True,... True, True, False]
,因为我们显示了前 100 个箱线图,然后显示了第一个没有丢弃空值的散点图,但随后不显示删除了空值的第二个散点图。并且 x_some
应该看起来像 [True...False... False... True, False, True]
因为一些空的箱线图痕迹不会被显示,然后我们不显示没有空值丢弃的第一个散点,但显示第二个散点有空值丢弃。
import pandas as pd
import numpy as np
import plotly.io as pio
import datetime as dt
import plotly.graph_objects as go
pio.renderers.default = 'browser'
pd.options.plotting.backend = "plotly"
fig = go.Figure()
N = 100
ydata = np.random.randint(600, 1200, size=(100, 5))
x = ["R"+str(i) for i in range(len(ydata))]
df = pd.DataFrame(ydata, columns=["M1", "M2", "M3", "M4", "M5"])
df["X"] = x
gaps = np.r_[20:40, 60:70]
df.iloc[gaps, 0:5] = np.nan
df["Mean"] = df.iloc[:, 0:5].mean(axis=1).round(0)
cols = df.columns.str.contains("M")
# figure setup
layout = dict(
height=700, width=1500,
xaxis_title="Run",
xaxis=dict(autorange=False, range=[0, N], type="category"),
yaxis=dict(autorange=True),
font=dict(family="Courier New, monospace", size=12, color="RebeccaPurple"),
showlegend=False
)
fig.layout = layout
mean_line = go.Scatter(x=df.X, y=df.Mean, connectgaps=True, mode='lines+markers', name='Mean line', showlegend=False)
## create mean line with excluded values missing (not visible by default)
df_non_null = df.dropna()
mean_line_exclude_missing = go.Scatter(x=df_non_null.X, y=df_non_null.Mean, connectgaps=False, mode='lines+markers', name='Mean line', showlegend=False, visible=False)
boxes = [go.Box(name=df.X[i], y=df.iloc[i, cols], boxpoints=False, boxmean=True, notched=True, showlegend=False) for i in range(N)]
fig.add_traces(boxes)
x_all = df.index == df.index
x_all = np.append(x_all, [True, False])
x_some = (df.Mean > 0).values
x_some = np.append(x_some, [False, True])
## the last two traces will be the mean line, and the mean line (with nulls excluded)
fig.add_trace(mean_line)
fig.add_trace(mean_line_exclude_missing)
fig.update_layout(updatemenus=[
dict(type="dropdown", direction="down", buttons=list([
dict(label="Include missing data", method="update", args=[{"visible": x_all}]),
dict(label="Exclude missing data", method="update", args=[{"visible": x_some}])
]), pad={"l": 10, "t": 10}, showactive=True, x=0.23, xanchor="left", y=1.1, yanchor="top")])
z = fig.to_dict()
fig.show()