You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Streamlit中实现Plotly散点图点击高亮同组数据点

实现Streamlit中点击数据点高亮同组所有项的方案

可以通过结合Plotly的图形样式自定义和Streamlit的会话状态(session_state)+点击事件监听来实现需求,以下是完整实现代码:

import pandas as pd
import plotly.express as px
import streamlit as st

# 初始化会话状态,保存选中的分组
if "selected_group" not in st.session_state:
    st.session_state.selected_group = None

# 创建示例数据
df = pd.DataFrame(dict(
    x=[4, 5, 1, 3, 2, 2],
    y=[3, 1, 7, 9, 8, 3],
    group=[0, 0, 0, 1, 1, 1],
    value=[1, 2, 3, 4, 5, 6],
    hover=['s1', 's2', 's3', 's4', 's5', 's6']
))

# 生成基础散点图
fig = px.scatter(
    df,
    y='y',
    x='x',
    color='group',
    hover_name='hover',
    color_discrete_map={0: "#1f77b4", 1: "#ff7f0e"}  # 自定义分组颜色
)

# 根据选中的分组更新图形样式
if st.session_state.selected_group is not None:
    for trace in fig.data:
        # 判断当前trace对应的分组是否为选中分组
        if trace.name == str(st.session_state.selected_group):
            # 高亮选中分组:放大尺寸、不透明、添加边框
            trace.marker.size = 15
            trace.marker.opacity = 1
            trace.marker.line.width = 2
            trace.marker.line.color = "black"
        else:
            # 暗淡非选中分组:缩小尺寸、降低透明度
            trace.marker.size = 8
            trace.marker.opacity = 0.3

# 渲染图表并监听点击事件
plot = st.plotly_chart(fig, on_select="rerun", key="scatter_plot")

# 处理点击事件,获取选中的分组
if plot.click_data:
    # 从点击数据中提取对应点的group值
    clicked_group = plot.click_data["points"][0]["customdata"][0]
    # 如果点击的是已选中的分组,取消高亮;否则设置为选中分组
    if st.session_state.selected_group == clicked_group:
        st.session_state.selected_group = None
    else:
        st.session_state.selected_group = clicked_group
    # 强制页面重跑以更新图表
    st.rerun()

功能说明

  • 点击任意数据点,同组的所有点会自动高亮(放大尺寸、添加黑色边框、保持完全不透明),其他组的点会变暗缩小
  • 再次点击已高亮组的任意点,会取消高亮,恢复初始样式
  • 利用st.session_state保存选中状态,确保页面重跑后状态不丢失
  • 通过修改Plotly图形的trace.marker属性实现样式切换,无需额外依赖

内容的提问来源于stack exchange,提问作者Oliver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 01:35:45