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

如何用Matplotlib和Python创建贷款组合分析用分组堆叠比例拆分柱状图?

实现贷款组合风险敞口的复杂堆叠拆分柱状图

以下是满足所有需求的完整实现代码,同时附带关键逻辑的详细说明:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

def loan_analysis(data, ax):
    # 1. 数据预处理:转换单位、排序优先级、计算占比
    chart_data = data.copy()
    # 统一转换为百万美元单位
    chart_data[['FMV', 'Amount']] = chart_data[['FMV', 'Amount']] / 1000000
    
    # 定义Level的优先级顺序,确保堆叠严格按1st→2nd→3rd排序
    level_order = ['1st', '2nd', '3rd']
    chart_data['Level'] = pd.Categorical(chart_data['Level'], categories=level_order, ordered=True)
    chart_data = chart_data.sort_values(['Loan', 'Level', 'Fund'])
    
    # 计算每个Loan-Level组合的总金额,用于拆分柱子宽度
    chart_data['Level_Total'] = chart_data.groupby(['Loan', 'Level'])['Amount'].transform('sum')
    # 计算单个Fund在对应Level中的金额占比,确定柱子宽度比例
    chart_data['Fund_Share'] = chart_data['Amount'] / chart_data['Level_Total']
    
    # 获取唯一贷款列表,分配x轴位置
    unique_loans = chart_data['Loan'].unique()
    loan_x_pos = np.arange(len(unique_loans))
    bar_width = 0.3  # 风险敞口柱子的总宽度
    fmv_bar_width = 0.2  # FMV柱子的宽度
    fmv_x_offset = 0.4  # FMV柱子相对于贷款位置的偏移量
    
    # 为每个Fund分配唯一配色
    unique_funds = chart_data['Fund'].unique()
    fund_colors = plt.cm.tab10(np.linspace(0, 1, len(unique_funds)))
    fund_color_map = dict(zip(unique_funds, fund_colors))
    
    # 2. 绘制风险敞口的复杂堆叠拆分柱状图
    for loan_idx, loan in enumerate(unique_loans):
        loan_data = chart_data[chart_data['Loan'] == loan]
        bottom = 0  # 堆叠的底部初始位置
        
        # 按Level优先级顺序处理堆叠
        for level in level_order:
            level_data = loan_data[loan_data['Level'] == level]
            if level_data.empty:
                continue
            
            level_total = level_data['Level_Total'].iloc[0]
            current_x = loan_x_pos[loan_idx] - bar_width/2  # 当前Level的起始x坐标
            
            # 遍历每个Fund,绘制对应宽度的分段柱子
            for _, row in level_data.iterrows():
                fund_bar_width = bar_width * row['Fund_Share']
                ax.bar(current_x, row['Amount'], width=fund_bar_width, bottom=bottom, 
                       color=fund_color_map[row['Fund']], edgecolor='white')
                # 更新下一个Fund的起始x坐标
                current_x += fund_bar_width
            
            # 更新堆叠的底部位置
            bottom += level_total
    
    # 3. 绘制FMV柱状图
    fmv_data = chart_data.drop_duplicates(subset=['Loan']).set_index('Loan')['FMV']
    ax.bar(loan_x_pos + fmv_x_offset, fmv_data.values, width=fmv_bar_width, 
           color='darkgreen', edgecolor='white', label='FMV')
    
    # 4. 图表格式化
    ax.set_xticks(loan_x_pos)
    ax.set_xticklabels(unique_loans)
    ax.set_xlabel('LOAN')
    
    # 自定义y轴为百万美元格式
    def dollar_fmt(x, pos):
        return f'${x:.2f}M'
    ax.yaxis.set_major_formatter(ticker.FuncFormatter(dollar_fmt))
    
    # 网格与样式优化
    ax.grid(axis='y', which='major', color='lightblue', lw=0.1)
    ax.grid(axis='y', which='minor', color='lightblue', lw=0.05)
    ax.tick_params(which='minor', length=0)
    ax.tick_params(axis='x', length=0)
    ax.tick_params(axis='y', length=0)
    ax.minorticks_on()
    
    # 手动构建图例,包含Fund颜色标识和FMV项
    fund_patches = [plt.Rectangle((0,0),1,1, color=fund_color_map[fund]) for fund in unique_funds]
    ax.legend(fund_patches + [plt.Rectangle((0,0),1,1, color='darkgreen')], 
              list(unique_funds) + ['FMV'], loc='upper right')
    
    return ax

# 示例数据
sample_data = pd.DataFrame({
    "Loan": ["123", "123", "124", "124", "124", "124"],
    "Level": ["1st", "1st", "1st", "2nd", "2nd", "3rd"],
    "FMV": [1000000, 1000000, 3000000, 3000000, 3000000, 3000000],
    "Fund": ["A", "B", "B", "A", "C", "D"],
    "Amount": [250000, 250000, 1000000, 700000, 300000, 200000]
})

# 生成图表
fig = plt.figure(figsize=(14, 8.5))
ax = plt.axes()
loan_analysis(sample_data, ax)
plt.tight_layout()
plt.show()

关键实现说明

1. 数据预处理逻辑

  • 将金额单位统一转换为百万美元,降低图表数值量级,提升可读性
  • 把Level设为有序分类类型,确保堆叠顺序严格遵循优先级
  • 计算每个Loan-Level的总金额,以及单个Fund在该层级的金额占比,这是实现宽度拆分的核心依据

2. 复杂柱状图绘制逻辑

  • 手动分配每个贷款的x轴位置,控制风险敞口柱子与FMV柱子的位置偏移,避免视觉重叠
  • 按1st→2nd→3rd的顺序逐层堆叠,累计每层总金额作为下一层的堆叠起点
  • 同一层级内,根据Fund的金额占比计算分段柱子的宽度,逐个绘制并分配对应颜色

3. 样式优化

  • 为每个Fund分配唯一的tab10色系,保证颜色区分度
  • 自定义y轴格式为百万美元显示,简化数值阅读
  • 手动构建图例,同时包含所有Fund的颜色标识和FMV的图例项

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:31:05