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

如何在Streamlit应用中获取Plotly平行坐标图的选中数据?

如何在Streamlit中实现Plotly平行坐标图选中数据实时展示表格?

核心问题说明

Streamlit原生的st.plotly_chart无法直接捕获Plotly图表的选中事件数据,因其交互模型不支持类似Dash的前端回调,需通过自定义HTML嵌入的方式实现数据交互。

解决方案:自定义HTML嵌入Plotly图表并捕获选中事件

通过streamlit.components.v1.html嵌入Plotly图表,用JavaScript监听图表的select事件,将选中的行索引传回Streamlit,再筛选对应数据展示。

完整代码示例:

import plotly.express as px
import streamlit as st
from streamlit.components.v1 import html
import json

# 加载数据
df = px.data.iris()
# 创建平行坐标图
fig = px.parallel_coordinates(
    df,
    color="species_id",
    dimensions=['sepal_width', 'sepal_length', 'petal_width', 'petal_length'],
    color_continuous_scale=px.colors.diverging.Tealrose,
    color_continuous_midpoint=2
)

# 将图表转为JSON格式
fig_json = fig.to_json()

# 自定义HTML模板,包含JS监听选中事件
html_template = f"""
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="plot"></div>
<script>
    const fig = JSON.parse('{fig_json}');
    Plotly.newPlot('plot', fig.data, fig.layout);

    // 监听选中事件
    document.getElementById('plot').on('plotly_selected', function(eventData) {{
        if (eventData.points.length > 0) {{
            // 获取选中的行索引
            const selectedIndices = eventData.points.map(point => point.pointNumber);
            // 将数据发送回Streamlit
            window.parent.postMessage({{
                type: 'plotly_selection',
                data: selectedIndices
            }}, '*');
        }}
    }});
</script>
"""

# 嵌入图表
html(html_template, height=600)

# 接收前端传来的选中数据
selected_indices = st.session_state.get('selected_indices', [])

# 展示选中的数据表格
if selected_indices:
    selected_df = df.iloc[selected_indices]
    st.subheader("选中的数据")
    st.dataframe(selected_df)
else:
    st.subheader("未选中任何数据")

# 使用JS回调捕获前端消息
st.components.v1.html("""
<script>
    window.addEventListener('message', function(event) {
        if (event.data.type === 'plotly_selection') {
            // 将数据存入Streamlit的session state
            window.parent.document.querySelector('iframe').contentWindow.postMessage({{
                type: 'streamlit:setSessionState',
                key: 'selected_indices',
                value: event.data.data
            }}, '*');
            // 触发Streamlit重新运行
            window.parent.document.querySelector('.stButton button').click();
        }
    });
</script>
""", height=0)

# 隐藏的按钮用于触发重新运行(不可见)
with st.container():
    st.markdown("<style>.stButton {visibility: hidden;}</style>", unsafe_allow_html=True)
    if st.button('Refresh'):
        pass

替代方案:使用Altair实现交互

如果不想自定义HTML,Altair是更适配Streamlit的可视化库,原生支持选择交互,无需额外JS代码:

import altair as alt
import streamlit as st
from vega_datasets import data

df = data.iris()

# 创建平行坐标图和选择器
brush = alt.selection_interval()
chart = alt.Chart(df).transform_window(
    index='count()'
).transform_fold(
    ['sepalLength', 'sepalWidth', 'petalLength', 'petalWidth'],
    as_=['dimension', 'value']
).mark_line().encode(
    x='dimension:N',
    y='value:Q',
    color='species:N',
    detail='index:N',
    opacity=alt.condition(brush, alt.value(1), alt.value(0.1))
).add_params(brush)

# 展示图表
st.altair_chart(chart, use_container_width=True)

# 展示选中的数据
selected_df = df.iloc[brush['index']] if brush['index'] else df
st.dataframe(selected_df)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:42:50