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

如何在Plotly/Streamlit中按行展示fname对应的饼图数据?

针对你的DataFrame交互式仪表盘实现方案

一、单个Fname选中时的饼图最优实现

用Plotly Dash做交互式绑定是适配仪表盘需求的最佳方案,核心逻辑是通过选择器触发饼图数据源的实时过滤:

1. 数据预处理

先将宽表转换为饼图所需的长格式:

import pandas as pd
import plotly.express as px
import dash
from dash import dcc, html, Input, Output

# 构造你的目标DataFrame
df = pd.DataFrame({
    'fname': ['A', 'B', 'C'],
    'col1': [2, 1, 6],
    'col2': [3, 2, 6],
    'col3': [3, 3, 3],
    'sum': [10, 12, 13]
})

# 转长表:把col1/col2/col3转为「类别-数值」的键值对结构
long_df = df.melt(id_vars='fname', value_vars=['col1', 'col2', 'col3'], 
                  var_name='column', value_name='value')

2. 交互式仪表盘代码

通过下拉选择器绑定饼图,选中单个fname时自动生成对应行的列数据饼图:

app = dash.Dash(__name__)

app.layout = html.Div([
    html.H3("Fname列数据分布饼图"),
    # 下拉选择器,包含「全选」选项
    dcc.Dropdown(
        id='fname-picker',
        options=[
            {'label': '全部Fname', 'value': 'all'},
            *[{'label': name, 'value': name} for name in df['fname'].unique()]
        ],
        value='all',
        clearable=False
    ),
    dcc.Graph(id='pie-output')
])

@app.callback(
    Output('pie-output', 'figure'),
    Input('fname-picker', 'value')
)
def update_chart(selected):
    if selected != 'all':
        # 过滤选中fname的数据,生成饼图
        filtered_data = long_df[long_df['fname'] == selected]
        fig = px.pie(filtered_data, values='value', names='column',
                     title=f"{selected}的各列数值占比",
                     hole=0.3) # 可选甜甜圈样式,提升可读性
        return fig
    # 全选逻辑见下方方案

二、全选Fname时的展示方案(3种实用选项)

全选时不推荐使用sunburst(易造成视觉混乱),推荐以下3种清晰的展示方式:

1. 堆叠条形图(对比各Fname的列数值)

适合直观对比每个fname下各列的数值大小:

# 替换update_chart函数中的全选分支
fig = px.bar(df, x='fname', y=['col1', 'col2', 'col3'],
             barmode='stack', title='所有Fname的列数值堆叠对比')
return fig

2. 分组子饼图(保持比例展示)

每个fname对应一个独立饼图,并排展示各列占比:

# 替换全选分支,需导入子图模块
from plotly.subplots import make_subplots
import plotly.graph_objects as go

fig = make_subplots(rows=1, cols=3, specs=[[{'type':'domain'}]*3])

for idx, name in enumerate(df['fname'].unique()):
    data = long_df[long_df['fname'] == name]
    fig.add_trace(go.Pie(labels=data['column'], values=data['value'], name=name),
                  1, idx+1)

fig.update_layout(
    title_text='所有Fname的列数值占比',
    annotations=[dict(text='A', x=0.12, y=0.5, showarrow=False),
                 dict(text='B', x=0.5, y=0.5, showarrow=False),
                 dict(text='C', x=0.88, y=0.5, showarrow=False)]
)
return fig

3. 均值聚合饼图(展示整体趋势)

计算所有行col1-col3的均值,展示整体比例分布:

# 替换全选分支
mean_data = df[['col1', 'col2', 'col3']].mean().reset_index()
mean_data.columns = ['column', 'value']
fig = px.pie(mean_data, values='value', names='column',
             title='所有Fname的列均值占比', hole=0.3)
return fig

三、修正你的Sunburst代码

你之前的sunburst效果混乱是因为层级顺序错误,应把fname作为最外层分类,调整后结构清晰:

# 先转长表
sunburst_data = df.melt(id_vars='fname', value_vars=['col1', 'col2', 'col3'],
                        var_name='column', value_name='value')
# 正确层级:fname -> column
fig = px.sunburst(sunburst_data, values='value', path=['fname', 'column'],
                  title='各Fname的列数值层级分布')
fig.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:01:44