【PostgreSQL数据分析实战:从数据清洗到可视化全流程】金融风控分析案例-10.3 风险指标可视化监控

👉 点击关注不迷路

👉 点击关注不迷路

👉 点击关注不迷路


文章大纲

PostgreSQL金融风控分析之风险指标可视化监控实战

一、引言

在金融领域,风险控制是核心环节之一。

  • 准确、及时地监控风险指标,对于金融机构做出明智决策、降低潜在损失至关重要。
  • PostgreSQL作为一款强大的开源关系型数据库,具备高效的数据存储、处理和分析能力,能够为金融风控分析提供坚实的数据基础。
  • 本文将结合实际案例,详细阐述如何利用PostgreSQL进行金融风控分析中的风险指标可视化监控,从数据清洗到可视化展示的全流程。

二、案例背景

某商业银行面临着日益复杂的金融风险环境,需要对贷款业务的风险进行全面监控。

  • 该银行拥有大量的客户数据、贷款数据、还款记录等,数据存储在PostgreSQL数据库中
  • 我们的目标是通过对这些数据的分析,提取关键的风险指标,并进行可视化展示,以便管理层和风控人员能够直观地了解风险状况,及时采取应对措施。

三、数据准备

(一)数据来源与字段说明

数据主要来源于银行的贷款业务系统,包括以下几个关键表:

    1. 客户信息表(customer_info):包含客户ID(customer_id)、姓名(customer_name)、年龄(age)、性别(gender)、职业(occupation)、信用评级(credit_rating)等字段。
    1. 贷款申请表(loan_application):包含贷款申请ID(application_id)、客户ID(customer_id)、贷款金额(loan_amount)、贷款期限(loan_term)、申请日期(application_date)、贷款类型(loan_type)等字段。
    1. 还款记录表(repayment_record):包含还款记录ID(record_id)、贷款申请ID(application_id)、还款日期(repayment_date)、应还金额(due_amount)、实际还款金额(actual_repayment_amount)、是否逾期(is_overdue)等字段。
    • 建表语句及测试数据构造

      sql 复制代码
      -- 创建客户信息表
      CREATE TABLE IF NOT EXISTS customer_info (
          customer_id SERIAL PRIMARY KEY,
          customer_name VARCHAR(50) NOT NULL,
          age SMALLINT CHECK (age BETWEEN 18 AND 70),
          gender VARCHAR(1) CHECK (gender IN ('M', 'F')),
          occupation VARCHAR(30),
          credit_rating VARCHAR(10) CHECK (credit_rating IN ('优秀', '良好', '中等', '较差'))
      );
      
      -- 创建贷款申请表
      CREATE TABLE IF NOT EXISTS loan_application (
          application_id SERIAL PRIMARY KEY,
          customer_id INT NOT NULL REFERENCES customer_info(customer_id),
          loan_amount DECIMAL(12,2) CHECK (loan_amount > 0),
          loan_term SMALLINT CHECK (loan_term BETWEEN 6 AND 120),  -- 贷款期限(月)
          application_date DATE,
          loan_type VARCHAR(10) CHECK (loan_type IN ('信用贷款', '抵押贷款', '担保贷款'))
      );
      
      -- 创建还款记录表(修正:添加due_date应还日期字段)
      CREATE TABLE IF NOT EXISTS repayment_record (
          record_id SERIAL PRIMARY KEY,
          application_id INT NOT NULL REFERENCES loan_application(application_id),
          due_date DATE NOT NULL,  -- 新增:应还日期(关键字段)
          repayment_date DATE,  -- 实际还款日期
          due_amount DECIMAL(12,2) CHECK (due_amount > 0),  -- 应还金额
          actual_repayment_amount DECIMAL(12,2) CHECK (actual_repayment_amount >= 0),  -- 实际还款金额
          is_overdue BOOLEAN  -- 是否逾期(实际还款日期 > 应还日期)
      );
      
      -- 插入100条客户信息(使用随机函数生成)
      INSERT INTO customer_info (customer_name, age, gender, occupation, credit_rating)
      SELECT 
          '客户' || g.id,
          floor(random() * 53 + 18)::SMALLINT,  -- 18-70岁随机
          CASE WHEN random() > 0.5 THEN 'M' ELSE 'F' END,
          (ARRAY['教师','医生','程序员','公务员','自由职业','企业主','设计师','销售','工程师','学生'])[floor(random()*10)+1],
          (ARRAY['优秀','良好','中等','较差'])[floor(random()*4)+1]
      FROM generate_series(1,100) AS g(id);
      
      -- 插入300条贷款申请记录(每个客户1-3条)
      INSERT INTO loan_application (customer_id, loan_amount, loan_term, application_date, loan_type)
      SELECT 
          (random() * 100 + 1)::INT,  -- 随机关联客户ID(1-100)
          floor(random() * 495000 + 5000)::DECIMAL(12,2),  -- 5000-500000元随机金额
          floor(random() * 115 + 6)::SMALLINT,  -- 6-120期随机期限
          (current_date - (random() * 1825)::INT)::DATE,  -- 最近5年随机申请日期(1825天≈5年)
          (ARRAY['信用贷款','抵押贷款','担保贷款'])[floor(random()*3)+1]
      FROM generate_series(1,300);
      
      -- 还款记录表数据(修正:通过子查询解决别名引用)
      INSERT INTO repayment_record (application_id, due_date, repayment_date, due_amount, actual_repayment_amount, is_overdue)
      WITH temp_data AS (
          SELECT 
              la.application_id,
              la.application_date + (g.id * 30)::INT AS due_date,
              CASE 
                  WHEN random() > 0.3 THEN la.application_date + (g.id * 30)::INT + (random() * 15)::INT  -- 30%逾期(+0-15天)
                  ELSE la.application_date + (g.id * 30)::INT - (random() * 5)::INT  -- 70%正常(-0-5天)
              END AS repayment_date,
              la.monthly_due AS due_amount,
              CASE 
                  WHEN random() > 0.05 THEN la.monthly_due  -- 95%正常还款
                  ELSE floor(random() * la.monthly_due)::DECIMAL(12,2)  -- 5%部分还款
              END AS actual_repayment_amount
          FROM (
              SELECT 
                  application_id,
                  application_date,
                  loan_term,
                  loan_amount / loan_term AS monthly_due
              FROM loan_application
          ) la
          CROSS JOIN generate_series(1,4) AS g(id)
      )
      SELECT 
          application_id,
          due_date,
          repayment_date,
          due_amount,
          actual_repayment_amount,
          (repayment_date > due_date) AS is_overdue  -- 现在可以安全引用repayment_date别名
      FROM temp_data
      LIMIT 1200;

(二)数据清洗

    1. 缺失值处理:通过SQL查询检查各表中的缺失值情况。
    • 对于客户信息表中的信用评级字段,若存在缺失值,根据客户的其他信息(如职业、收入等)进行合理填充,或者将其标记为未知类别。
    • 对于贷款申请表中的贷款期限字段,若存在缺失值,由于该字段是关键信息,无法通过其他字段推断,因此删除相应的缺失记录。
sql 复制代码
-- 检查客户信息表信用评级缺失值
SELECT COUNT(*) FROM customer_info WHERE credit_rating IS NULL;

-- 填充信用评级缺失值(示例,实际需根据业务规则)
UPDATE customer_info SET credit_rating = 'medium' WHERE credit_rating IS NULL AND occupation = 'employee';

-- 删除贷款申请表中贷款期限缺失的记录
DELETE FROM loan_application WHERE loan_term IS NULL;
    1. 异常值处理:对于贷款金额字段,通过统计分析确定合理的范围,将明显超出正常范围的异常值视为错误数据并进行修正或删除。
    • 例如,贷款金额不能为负数,若存在负数记录,检查是否为输入错误,若是则进行修正,否则删除。
sql 复制代码
-- 检查贷款金额异常值(负数)
SELECT * FROM loan_application WHERE loan_amount < 0;

-- 删除贷款金额为负数的异常记录
DELETE FROM loan_application WHERE loan_amount < 0;
    1. 数据一致性检查:确保各表之间的数据关联正确,例如贷款申请表中的客户ID必须存在于客户信息表中,还款记录表中的贷款申请ID必须存在于贷款申请表中。
    • 通过外键约束或SQL查询进行检查,对于不匹配的数据进行修正或删除。
sql 复制代码
-- 检查贷款申请表中客户ID不存在于客户信息表的记录
SELECT la.* FROM loan_application la LEFT JOIN customer_info ci ON la.customer_id = ci.customer_id WHERE ci.customer_id IS NULL;

-- 删除不匹配的贷款申请记录
DELETE FROM loan_application WHERE customer_id NOT IN (SELECT customer_id FROM customer_info);

四、风险指标计算

(一)逾期率计算

逾期率是衡量贷款风险的重要指标之一,它表示逾期还款的贷款占总贷款的比例。

  • 计算公式为:逾期率 = 逾期贷款笔数 / 总贷款笔数 × 100%。

在PostgreSQL中,通过以下SQL语句计算各贷款类型的逾期率:

sql 复制代码
SELECT loan_type, 
       COUNT(CASE WHEN is_overdue = 'yes' THEN 1 END) AS overdue_loans,
       COUNT(*) AS total_loans,
       ROUND(COUNT(CASE WHEN is_overdue = 'yes' THEN 1 END) * 100.0 / COUNT(*), 2) AS overdue_rate
FROM loan_application la
JOIN repayment_record rr ON la.application_id = rr.application_id
GROUP BY loan_type;

计算结果如下表所示:

(二)不良贷款率计算

不良贷款率是指不良贷款(通常指逾期90天以上的贷款)占总贷款的比例。

  • 计算公式为:不良贷款率 = 不良贷款笔数 / 总贷款笔数 × 100%。

首先,需要确定逾期90天以上的贷款记录。

  • 通过计算还款日期与应还日期的时间差,判断是否逾期90天以上。
  • 在PostgreSQL中,使用AGE函数计算时间差:
sql 复制代码
SELECT rr.record_id, la.application_id, la.loan_type, 
       AGE(rr.repayment_date, due_date) AS days_overdue
FROM repayment_record rr
JOIN loan_application la ON rr.application_id = la.application_id;
  • 然后,计算不良贷款率:
sql 复制代码
SELECT loan_type, 
       COUNT(CASE WHEN days_overdue > '90 days' THEN 1 END) AS bad_loans,
       COUNT(*) AS total_loans,
       ROUND(COUNT(CASE WHEN days_overdue > '90 days' THEN 1 END) * 100.0 / COUNT(*), 2) AS bad_loan_rate
FROM (
    SELECT rr.record_id, la.application_id, la.loan_type, 
           AGE(rr.repayment_date, due_date) AS days_overdue
    FROM repayment_record rr
    JOIN loan_application la ON rr.application_id = la.application_id
) AS subquery
GROUP BY loan_type;

计算结果如下表所示:

(三)客户信用评分分布

客户信用评级是评估客户信用风险的重要依据。

  • 通过统计不同信用评级的客户数量及其占比,了解客户的信用状况分布。
sql 复制代码
SELECT credit_rating, 
       COUNT(*) AS customer_count,
       ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM customer_info), 2) AS percentage
FROM customer_info
GROUP BY credit_rating
ORDER BY credit_rating;

结果如下表:

五、风险指标可视化

(一)可视化工具选择

为了实现风险指标的可视化监控,我们选择使用Tableau作为可视化工具。

  • Tableau具有强大的数据可视化能力,能够快速将PostgreSQL中的数据转化为直观、交互式的图表和仪表盘,方便用户进行数据分析和监控。

(二)可视化图表设计

    1. 逾期率对比柱状图 :以贷款类型为横轴,逾期率为纵轴,绘制柱状图,直观展示不同贷款类型的逾期率差异。
    • 通过颜色区分不同的贷款类型,使图表更加清晰易读。
    1. 不良贷款率趋势线图 :按时间维度(如月份)统计不良贷款率,绘制趋势线图,观察不良贷款率的变化趋势。
    • 可以设置预警线,当不良贷款率超过预警线时,发出警示信号。
    1. 客户信用评分饼图以信用评级为分类,绘制饼图,展示不同信用评级客户的占比情况
    • 通过标签显示具体的占比数据,方便用户快速了解客户信用分布。

(三)仪表盘搭建

将上述可视化图表整合到一个仪表盘上,形成风险指标可视化监控界面。

  • 仪表盘可以包含筛选器,允许用户根据不同的条件(如时间范围、贷款类型等)进行数据筛选,查看相应的风险指标。
  • 同时,设置交互功能,当用户点击某个图表中的数据时,其他相关图表会进行联动更新,以便更深入地分析数据。

六、结论与建议

(一)结论

通过利用PostgreSQL进行金融风控分析中的风险指标可视化监控,我们能够有效地对贷款业务的风险进行评估和监控。

  • 数据清洗到风险指标计算,再到可视化展示,整个流程实现了数据的高效处理和分析,为金融机构提供了直观、准确的风险信息
  • 通过对不同贷款类型的逾期率、不良贷款率以及客户信用评分分布的分析,我们可以发现信用贷款的风险相对较高,需要重点关注和加强风控措施。

(二)建议

    1. 针对信用贷款的高风险特点,进一步优化信用评估模型,加强对信用评级较低客户的审核和监控,提高信用贷款的准入门槛。
    1. 定期更新和维护风险指标可视化仪表盘,确保数据的及时性和准确性。同时,根据业务需求和市场变化,不断优化可视化图表和指标体系,提高监控的有效性。
    1. 结合其他数据分析方法和技术,如机器学习算法,对客户的信用风险进行更精准的预测和评估,为风险控制提供更科学的依据。

通过以上实战案例,我们展示了如何利用PostgreSQL和Tableau实现金融风控分析中的风险指标可视化监控。

  • 这一流程不仅适用于商业银行的贷款业务风险监控,也可以为其他金融领域的风险分析提供参考和借鉴。

  • 在实际应用中,需要根据具体的业务需求和数据特点,灵活调整分析方法和可视化方案,以实现更好的风险控制效果。
    以上是完整的金融风控分析案例中风险指标可视化监控内容。

  • 你可以和我说说对文章内容、结构等方面的看法,若有其他修改或补充需求,也请告知我。

相关推荐
小L爱科研12 分钟前
4.7/Q1,GBD数据库最新文章解读
数据库·机器学习·数据分析·回归·健康医疗
chennalC#c.h.JA Ptho42 分钟前
kubuntu系统详解
linux·数据库·经验分享·postgresql·系统安全
kngines1 小时前
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】金融风控分析案例-10.4 模型部署与定期评估
postgresql·数据分析·存储过程·jsonb·pg_cron·ks值·影子测试机制
想看雪的瓜1 小时前
Nature图形复现—两种快速绘制热图的方法
信息可视化·数据挖掘·数据分析
镜舟科技1 小时前
湖仓一体架构在金融典型数据分析场景中的实践
starrocks·金融·架构·数据分析·湖仓一体·物化视图·lakehouse
生信大杂烩4 小时前
R语言绘图 | 渐变火山图
数据分析·r语言
Hello world.Joey4 小时前
数据挖掘入门-二手车交易价格预测
人工智能·python·数据挖掘·数据分析·conda·pandas
kngines7 小时前
【PostgreSQL数据分析实战:从数据清洗到可视化全流程】金融风控分析案例-10.1 风险数据清洗与特征工程
postgresql·z-score·缺失值处理·levenshtein·信用评分波动率·分箱处理·woe编码
weixin_4723394611 小时前
Postgresql与openguass对比
数据库·postgresql