【问题标题】:Display only single line on hover, hide all other lines悬停时仅显示单行,隐藏所有其他行
【发布时间】:2021-09-22 14:46:58
【问题描述】:

当我悬停单个线条时,有没有办法隐藏图形上的所有其他线条?

例子:

import numpy as np
import plotly.express as px

np.random.seed(42)
data = np.random.randint(0, 10, (5, 10))
fig = px.line(data_frame=pd.DataFrame(data))

fig.show()

将产生:

我想要这个,当我悬停特定线时(但没有手动关闭所有其他线并保持 X、Y 轴变暗):

UPD:在 jupyter 笔记本内部

【问题讨论】:

  • 希望在 jupyter notebook 或 html 文件中完成此任务?
  • @It_is_Chris 抱歉,在 jupyter 里面
  • @banderlog013 你愿意在 JupyterLab 中使用 Dash 吗?
  • @banderlog013 你想如何在点击时恢复隐藏的痕迹?
  • @vestland nope,普通的 jupyter

标签: python plotly plotly-python


【解决方案1】:
import plotly.graph_objects as go
import numpy as np
import pandas as pd

# callback function for on_hover
def hide_traces_on_hover(trace, points, selector):
    if len(points.point_inds)==1: # identify hover
        i = points.trace_index # get the index of the hovered trace
        f.data[i].visible = True # keep the hovered trace visible
        # create a list of traces you want to hide
        hide_traces = [l_trace for idx, l_trace in enumerate(f.data) if idx != i] 
        for l_trace in hide_traces: # iterate over hide_traces
            l_trace.visible = 'legendonly' # hide all remaining traces
    
# callback function to unhide traces on click
def unhide_traces_on_click(trace, points, selector):
    for l_trace in f.data:
        l_trace.visible = True
        
# your sample data frame
np.random.seed(42)
data = np.random.randint(0, 10, (5, 10))
df = pd.DataFrame(data)

f = go.FigureWidget() # create figure widget

f.update_yaxes(autorange=False) # set auto range to false
# define the range of the y-axis using min and max functions
f.update_layout(yaxis_range=[df.values.min()-1, df.values.max()+1])

# create your traces from the data frame
for col in df.columns:
    trace = go.Scatter(x=df.index, y=df[col], mode='lines+markers')
    f.add_trace(trace)

# assign your functions to each trace
for trace in f.data:
    trace.on_hover(hide_traces_on_hover)
    trace.on_click(unhide_traces_on_click)

f

如果您遇到问题,这里是 jupyter notebook support documentation 用于使用 FigureWidget,这里是 jupyter lab support documentation。确保您已安装 ipywidgets 软件包。另外,仅供参考,这里是FigureWidget documentation

当您将鼠标悬停在图表中的标记上时。

当您单击可见迹线的任何标记时,所有隐藏的迹线将再次变得可见。

【讨论】:

  • @vestland 这是使用FigureWidgetjupyter notebook support documentation,这是jupyter lab suport documentation。确保您已安装 ipywidgets 软件包。安装后,您只需在笔记本中调用图形小部件f,而不是f.show()。另外,仅供参考,这里是FigureWidget documentation
  • 太棒了!您会考虑在答案中包含这些链接吗?我认为这确实会增加帖子的价值。
  • 只有当我将鼠标悬停在一个点上才有效,而不是一条线,连接两个点
  • @banderlog013 正确。我不熟悉任何其他方式,因为我相信 on_hoveron_click 属性只能在标记上交互。此外,通过这种方式,您仍然可以使用 plotly 的交互式图形功能来选择和放大某些数据点。
【解决方案2】:

以下建议来自Plotly Dash: How to reset the "n_clicks" attribute of a dash-html.button?Plotly-Dash: How to code interactive callbacks for hover functions in plotly dash 的帖子,您可以通过将鼠标悬停在线条的任何点或部分上来显示单个跟踪。其余的痕迹并没有完全隐藏,而是在背景中设置为灰色和透明,以便您更轻松地进行其他选择。

要重置图形并同时使所有痕迹完全可见,只需单击Clear Selection。我知道您更喜欢“简单”的 Jupyter 方法来获得此功能,但您会错过 plotly 的真正力量,它只能通过DashJupyterDash 才能充分展示自己。有了这个建议,您不会看到 Dash 和“普通”Jupyter 之间有任何区别,因为图形或应用程序与 app.run_server(mode='inline') 内联显示

情节 1 - 启动时。或点击Clear selection

情节 2 - 选择 = 跟踪 a

情节 3 - 选择 = 跟踪 b

完整代码

import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash

# pandas and plotly settings
pd.options.plotting.backend = "plotly"

# app info
app = JupyterDash(__name__)

# sample data and figure setup
df = pd.DataFrame(np.random.randint(-1,2,size=(200, 12)), columns=list('abcdefghijkl'))
df = df.cumsum()#.reset_index()
fig = df.plot(title = 'Selected traces = all', template='plotly_dark')#.update_traces(line_color = 'rgba(50,50,50,0.5)')
set_fig = go.Figure(fig)
colors = {d.name:d.line.color for i, d in enumerate(set_fig.data)}

# jupyterdash app
app.layout = html.Div([html.Button('Clear selection', id='clearit', n_clicks=0),
                       dcc.Graph(id='hoverfig',figure=fig,#clear_on_unhover = True
                                                ),])
colors = {d.name:d.line.color for i, d in enumerate(set_fig.data)}

# callbacks
@app.callback(
    Output('hoverfig', 'figure'),
    [Input('hoverfig', 'hoverData'), Input('clearit', 'n_clicks')])
def display_hover_data(hoverData, resetHover):
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0]
    if 'clearit' in changed_id:
        return set_fig
    else:
        try:
            fig2 = fig.update_layout(title = 'Selected trace = ' + fig.data[hoverData['points'][0]['curveNumber']].name)
            fig2.for_each_trace(lambda t: t.update(line_color = 'rgba(50,50,50,0.5)',line_width = 1) if t.name != fig.data[hoverData['points'][0]['curveNumber']].name else t.update(line_color = colors[t.name], line_width = 2))
            return fig2
        except:
            return fig

app.run_server(mode='inline', port = 8070, dev_tools_ui=True,
          dev_tools_hot_reload =True, threaded=True)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    相关资源
    最近更新 更多