EXCEL Python 实现绘制柱状线型组合图和树状图(包含数据透视表)

1、组合图、数据透视表

(1)数据预处理

知识点

  1. 日期函数 year() month()
  2. 数据透视表操作
  3. 同比计算公式
  4. 环比计算公式

(2)excel 数据透视表+插入组合图

a.2015~2017数据集处理方式:

  • 操作:
  • 结果

b.2020~2022数据集处理方式

一次数据透视结果:
  • 操作

  • 结果
两次数据透视结果
  • 操作:
  • 结果:

(3)python绘制组合图

a.数据预处理结果

b.代码

知识点:

  1. 使用 make_subplots 创建子图,设置 secondary_y=True 启用双 Y 轴

  2. 交互模式:hovermode='x unified' 使鼠标悬停时同时显示所有系列在同一日期的数据,便于对比。

python 复制代码
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 读取数据
data = pd.read_excel('组合图数据.xlsx',engine='openpyxl')

# 将日期列转换为datetime类型
data['日期'] = pd.to_datetime(data['日期'])

# 创建组合图
fig = make_subplots(specs=[[{"secondary_y": True}]])

# 添加成交金额柱状图
fig.add_trace(
    go.Bar(
        x=data['日期'],
        y=data['求和项:成交金额'],
        name='求和项:成交金额',
        marker_color='#1f77b4'
    ),
    secondary_y=False
)

# 添加同比增幅折线图
fig.add_trace(
    go.Line(
        x=data['日期'],
        y=data['同比'],
        name='同比增幅',
        line=dict(color='#d62728', width=2, dash='dash')
    ),
    secondary_y=True
)

# 添加环比增幅折线图
fig.add_trace(
    go.Line(
        x=data['日期'],
        y=data['环比'],
        name='环比增幅',
        line=dict(color='#2ca02c', width=2, dash='dash')
    ),
    secondary_y=True
)

# 设置图表布局
fig.update_layout(
    title='2020年1月1日-2022年12月1日的成交金额、环比增幅、同比增幅的组合图',
    xaxis_title='日期',
    yaxis_title='成交金额',
    yaxis2=dict(
        title='增幅 (%)',
        overlaying='y',
        side='right'
    ),
    hovermode='x unified'
)

# 显示图表
fig.show()

c.结果

组合图

优化:销售数据仪表盘:

a.代码

知识点

  1. dash 构建交互界面,dash_bootstrap_components 提供美观的 UI 组件。
  2. dbc.Container:Bootstrap 的响应式容器,fluid=True表示宽度 100%
  3. dbc.Row, dbc.Col:Bootstrap 的网格系统,一行一列。
  4. html.H1:HTML 标题标签,className添加样式(居中、上下边距)。
  5. dcc.Dropdown:下拉菜单组件:
    id:组件唯一标识,用于回调。
    options:选项列表,格式为[{label:显示文本, value:实际值}]。
    value:默认选中的值。
    multi=True:允许多选。
  6. dbc.Button:Bootstrap 按钮:
    n_clicks:记录点击次数,触发回调。
    color="primary":蓝色主按钮。
  7. dbc.Spinner:加载动画,在数据处理时显示。
  8. dcc.Graph:Plotly 图表组件,id='sales-graph'用于显示组合图。
  9. @app.callback:装饰器,定义回调函数。
  10. Output:回调输出,更新sales-graph组件的figure属性。
  11. Input:触发回调的输入,这里是按钮的n_clicks。
  12. State:获取下拉菜单当前值(不触发回调)。
  13. hovertemplate:鼠标悬停时显示的信息:
    %{x|%Y年%m月}:格式化日期(如 2023 年 01 月)。
    %{text}:显示text中的金额。
    < extra></ extra>:隐藏右侧默认信息。
  14. overlaying='y':与左侧 Y 轴共享 X 轴。
  15. hovermode='x unified':鼠标悬停时,所有数据在同一 X 轴对齐显示。
  16. tickformat='% Y 年 % m 月':X 轴日期格式化为2023年01月。
    tickformat=',':Y 轴数字添加千位分隔符(如1,000,000)。
  17. 流式布局(fluid layout)fluid=True 响应式布局适配不同屏幕。
python 复制代码
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import dash
from dash import dcc, html, Input, Output, State
import dash_bootstrap_components as dbc

# 读取数据
data = pd.read_excel('组合图数据.xlsx',engine='openpyxl')

# 确保日期列是正确的格式
data['日期'] = pd.to_datetime(data['日期'])
data['年份'] = data['日期'].dt.year
data['月份'] = data['日期'].dt.month

# 创建应用
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
server = app.server  # 用于生产部署

# 获取年份和月份的唯一值
years = sorted(data['年份'].unique())
months = list(range(1, 13))
month_names = ['一月', '二月', '三月', '四月', '五月', '六月',
               '七月', '八月', '九月', '十月', '十一月', '十二月']

# 应用布局
app.layout = dbc.Container([
    dbc.Row([
        dbc.Col(html.H1("销售数据分析仪表盘", className="text-center mt-4 mb-4"), width=12)
    ]),

    dbc.Row([
        dbc.Col([
            html.Label("选择年份:", className="mr-2"),
            dcc.Dropdown(
                id='year-dropdown',
                options=[{'label': str(year), 'value': year} for year in years],
                value=years,  # 默认选择所有年份
                multi=True,
                className="w-100"
            )
        ], width=3),

        dbc.Col([
            html.Label("选择月份:", className="mr-2"),
            dcc.Dropdown(
                id='month-dropdown',
                options=[{'label': month_names[i - 1], 'value': i} for i in months],
                value=months,  # 默认选择所有月份
                multi=True,
                className="w-100"
            )
        ], width=3),

        dbc.Col([
            dbc.Button(
                "应用筛选",
                id='apply-filter',
                n_clicks=0,
                className="mt-3",
                color="primary"
            )
        ], width=2)
    ], className="mb-4"),

    dbc.Row([
        dbc.Col([
            dbc.Spinner(
                id="loading-spinner",
                children=[dcc.Graph(id='sales-graph')],
                color="primary",
                type="grow"
            )
        ], width=12)
    ])

], fluid=True)


# 回调函数
@app.callback(
    Output('sales-graph', 'figure'),
    [Input('apply-filter', 'n_clicks')],
    [State('year-dropdown', 'value'),
     State('month-dropdown', 'value')]
)
def update_graph(n_clicks, selected_years, selected_months):
    # 确保参数有效
    if not selected_years:
        selected_years = years
    if not selected_months:
        selected_months = months

    # 筛选数据
    filtered_data = data[
        data['年份'].isin(selected_years) &
        data['月份'].isin(selected_months)
        ]

    # 如果没有数据,返回空图表
    if filtered_data.empty:
        fig = go.Figure()
        fig.update_layout(
            title="没有匹配的数据",
            xaxis_title="日期",
            yaxis_title="成交金额"
        )
        return fig

    # 创建组合图
    fig = make_subplots(specs=[[{"secondary_y": True}]])

    # 添加成交金额柱状图
    fig.add_trace(
        go.Bar(
            x=filtered_data['日期'],
            y=filtered_data['求和项:成交金额'],
            name='成交金额',
            text=[f"{x:,.0f}" for x in filtered_data['求和项:成交金额']],
            hovertemplate='日期: %{x|%Y年%m月}<br>成交金额: %{text}<extra></extra>',
            marker_color='#1f77b4'
        ),
        secondary_y=False
    )

    # 添加同比增幅折线图
    fig.add_trace(
        go.Scatter(
            x=filtered_data['日期'],
            y=filtered_data['同比'],
            name='同比增幅',
            text=[f"{x:.1f}%" for x in filtered_data['同比']],
            hovertemplate='日期: %{x|%Y年%m月}<br>同比增幅: %{text}<extra></extra>',
            line=dict(color='#d62728', width=2, dash='dash'),
            marker=dict(size=8)
        ),
        secondary_y=True
    )

    # 添加环比增幅折线图
    fig.add_trace(
        go.Scatter(
            x=filtered_data['日期'],
            y=filtered_data['环比'],
            name='环比增幅',
            text=[f"{x:.1f}%" for x in filtered_data['环比']],
            hovertemplate='日期: %{x|%Y年%m月}<br>环比增幅: %{text}<extra></extra>',
            line=dict(color='#2ca02c', width=2, dash='dash'),
            marker=dict(size=8)
        ),
        secondary_y=True
    )

    # 设置图表布局
    fig.update_layout(
        title=f"成交金额与增幅分析 ({', '.join(map(str, selected_years))}年)",
        title_font=dict(size=20),
        xaxis_title="日期",
        yaxis_title="成交金额",
        yaxis2=dict(
            title="增幅 (%)",
            overlaying='y',
            side='right'
        ),
        legend=dict(
            x=0, y=1.05,
            orientation='h',
            bgcolor='rgba(255, 255, 255, 0.8)',
            bordercolor='rgba(0, 0, 0, 0.1)',
            borderwidth=1,
            font=dict(size=14)
        ),
        hovermode='x unified',
        plot_bgcolor='rgba(240, 240, 240, 0.5)',
        margin=dict(l=60, r=60, t=60, b=60),
        font=dict(family="SimHei, WenQuanYi Micro Hei, Heiti TC", size=14)
    )

    # 设置X轴格式
    fig.update_xaxes(
        tickformat='%Y年%m月',
        tickfont=dict(size=14)
    )

    # 设置Y轴格式
    fig.update_yaxes(
        tickformat=',',
        title_font=dict(size=16)
    )

    return fig


if __name__ == '__main__':
    app.run_server(debug=True)
b.结果

销售数据仪表盘

2、树状图可视化

(1)数据预处理,数据透视表实现求和

(2)EXCEL 插入树状图

(3)python matplotlib库中的squarify.plot()函数绘制树状图

python 复制代码
import pandas as pd
import matplotlib.pyplot as plt
import squarify
import numpy as np

# 读取数据
df = pd.read_excel('树状图.xlsx', engine='openpyxl')

# 设置图片清晰度
plt.rcParams['figure.dpi'] = 300
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC']

# 数据预处理:计算占比,用于标签显示
total = df['求和项:成交金额'].sum()
df['占比'] = df['求和项:成交金额'].apply(lambda x: f"{x/total*100:.1f}%")

# 创建自定义颜色映射
cmap = plt.cm.get_cmap('viridis', len(df))
colors = [cmap(i) for i in range(len(df))]

# 绘制树状图
plt.figure(figsize=(12, 8))  # 设置图形大小

squarify.plot(
    sizes=df['求和项:成交金额'],
    label=[f"{name}\n{amount/1e8:.1f}亿\n{percent}"
           for name, amount, percent in zip(df['类别'], df['求和项:成交金额'], df['占比'])],
    color=colors,
    alpha=0.8,
    pad=True  # 添加间隔,使图形更清晰
)

# 设置标题和样式
plt.title('不同类别成交金额树状图', fontsize=16, pad=10)
plt.axis('off')  # 隐藏坐标轴

# 添加图例说明
plt.text(
    0.99, 0.01,
    f"总计: {total/1e8:.2f}亿",
    ha='right',
    va='bottom',
    transform=plt.gca().transAxes,
    fontsize=10,
    bbox=dict(facecolor='white', alpha=0.7)
)

# 调整布局
plt.tight_layout()

# 显示图形
plt.show()
相关推荐
shykevin2 小时前
python开发Streamable HTTP MCP应用
开发语言·网络·python·网络协议·http
漫路在线3 小时前
JS逆向-某易云音乐下载器
开发语言·javascript·爬虫·python
成功人chen某6 小时前
配置VScodePython环境Python was not found;
开发语言·python
听忆.6 小时前
前端上传获取excel文件后,如何读取excel文件的内容
excel
玩电脑的辣条哥6 小时前
怎么在excel单元格1-5行中在原来内容前面加上固定一个字?
excel
skd89996 小时前
小蜗牛拨号助手用户使用手册
python
「QT(C++)开发工程师」6 小时前
STM32 | FreeRTOS 递归信号量
python·stm32·嵌入式硬件
史迪仔01127 小时前
[python] Python单例模式:__new__与线程安全解析
开发语言·python·单例模式
胡耀超7 小时前
18.自动化生成知识图谱的多维度质量评估方法论
人工智能·python·自动化·知识图谱·数据科学·逻辑学·质量评估