Plotly update_menus隐藏轨迹问题

huangapple go评论46阅读模式
英文:

Plotly update_menus hiding traces problem

问题

以下是您要翻译的内容:

Newbie in Plotly with Python and StackOverflow here. I have created a figure that includes a number of box plots, a scatter plot and a few more elements that can be relayed out.

My data have gaps that I want to optionally toggle on and off from appearing in the graph using a dropdown list (see Image 1).

In one case, I can hide the gaps successfully but the scatter plot loses its X axis values and is graphed after the end of the labeled data (see Image 2). This is produced by this line of code: dict(label="Exclude missing data", method="update", args=[{"x":df.Run[x_some],"visible": x_some}])

In the other case I can hide the gaps in the data, the scatter plot works but the labels of the X axis that were "hidden" move to the end of the graph (see Image 3). This is produced by this line of code: dict(label="Exclude missing data", method="update", args=[{"visible": x_some}])

Are there any hints on what I'm doing wrong and how to fix this?

Please find some sample code below:

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 = , 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()
英文:

Newbie in Plotly with Python and StackOverflow here. I have created a figure that includes a number of box plots, a scatter plot and a few more elements that can be relayed out.

My data have gaps that I want to optionally toggle on and off from appearing in the graph using a dropdown list (see Image 1).

Plotly update_menus隐藏轨迹问题

In one case, I can hide the gaps successfully but the scatter plot loses its X axis values and is graphed after the end of the labeled data (see Image 2). This is produced by this line of code: dict(label="Exclude missing data", method="update", args=[{"x":df.Run[x_some],"visible": x_some}])

Plotly update_menus隐藏轨迹问题

In the other case I can hide the gaps in the data, the scatter plot works but the labels of the X axis that were "hidden" move to the end of the graph (see Image 3). This is produced by this line of code: dict(label="Exclude missing data", method="update", args=[{"visible": x_some}])

Plotly update_menus隐藏轨迹问题

Are there any hints on what I'm doing wrong and how to fix this?

Please find some sample code below:

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 = , 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()

答案1

得分: 0

发生这种情况的原因是因为你忘记考虑最后一个散点图,它仍然包含NaN的x值。(这里有100个箱线图和1个散点图,所以x_allx_some实际上应该有长度101 - 在你的原始代码中,这两个布尔数组的长度是100,但是Plotly假设你想要显示最后一个散点图)

为了解决这个问题,我们可以添加另一个散点图,其中包含缺失值 - 我们可以将其默认设置为不可见,并且只有在你从下拉菜单中选择“排除缺失数据”时才显示这个散点图。

注意:x_allx_some现在将有长度102。x_all应该看起来像[True,... True, True, False],因为我们显示了前100个箱线图,然后显示了第一个散点图,没有删除null值,然后不显示第二个散点图,它已经删除了null值。x_some应该看起来像[True...False... False... True, False, True],因为一些空的箱线图不会被显示,然后我们不显示第一个散点图,但是显示了删除了null值的第二个散点图。

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 = , 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()
英文:

The reason this is occurring is because you forgot to account for the last trace which is the scatter, and it still includes x-values that are NaN. (there are 100 box traces and 1 scatter trace, so x_all and x_some should actually have length 101 – in your original code, these two boolean arrays have length 100, but plotly assumes that you mean to show the last scatter trace)

To fix this, we can add another scatter trace with missing values dropped – we can make this not visible by default, and only show this scatter when you select the "Exclude missing data" from the dropdown.

Note: x_all and x_some will now have length 102. x_all should look like [True,... True, True, False] because we show the first 100 boxplots, and then show the first scatter without nulls dropped, but then don't show the second scatter which has nulls dropped. And x_some should look like [True...False... False... True, False, True] because some of the box plots traces that are empty won't be shown, and then we don't show the first scatter without nulls dropped, but show the second scatter which has nulls dropped.

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 = , 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()

Plotly update_menus隐藏轨迹问题

huangapple
  • 本文由 发表于 2023年3月9日 23:57:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687079.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定