一、问题背景:如何批量生成判断结论?
前文“鲁泰A:十年数据看“成长的滞性”与“盈利的困境””中关于营业收入与净利润的关系分析,即“备注栏”是用python代码生成的。
年度 | 营业收入(亿元) | 营收增长率 | 归母净利润(亿元) | 净利润增长率 | 备注 |
2016 | 59.90 | - | 8.09 | - | 数据缺失 |
2017 | 64.09 | 7.0% | 8.41 | 4.0% | 杠杆失灵(弹性不足) |
2018 | 68.97 | 7.6% | 8.91 | 5.9% | 杠杆失灵(弹性不足) |
2019 | 74.84 | 8.5% | 9.88 | 10.9% | 正常(杠杆效应发挥) |
2020 | 59.04 | -21.1% | 4.03 | -59.2% | 正常(杠杆效应发挥) |
2021 | 52.57 | -11.0% | 3.51 | -12.9% | 正常(杠杆效应发挥) |
2022 | 69.38 | 32.0% | 9.64 | 174.6% | 正常(杠杆效应发挥) |
2023 | 60.91 | -12.2% | 4.10 | -57.5% | 正常(杠杆效应发挥) |
2024 | 60.91 | 0% | 4.10 | 0% | 杠杆失灵(弹性不足) |
2025 | 59.04 | -3.06% | 5.94 | 44.7% | 异常·方向背离 |
本文将展示如何用Python构建一个自动诊断模型,让机器替我们判断杠杆效应的健康状态。
二、核心思路:用“关系系数”量化杠杆效应
我们先定义一个关键指标:
关系系数= 净利润增长率 ÷ 营业收入增长率
这个系数的经济含义非常直观:
系数> 1:净利润增长快于收入增长,杠杆效应发挥
系数= 1:净利润与收入同比例增长,无杠杆效应
系数< 1:净利润增长慢于收入增长,杠杆失灵
系数< 0:净利润与收入反向变动,方向背离(危险信号)
诊断标准的设定逻辑
根据大量上市公司财务数据的实证观察,我们将关系系数划分为六个诊断区间:
关系系数区间 | 诊断结论 | 业务含义 |
< 0 | 异常·方向背离 | 收入增、利润降,或收入降、利润增,需紧急排查 |
0 ~ 1 | 杠杆失灵(费用上升) | 收入增长被成本费用吞噬,盈利能力恶化 |
1 ~ 1.1 | 杠杆失灵(弹性不足) | 杠杆效应微弱,接近无杠杆状态 |
1.1 ~ 20 | 正常(杠杆效应发挥) | 利润增长适度快于收入,经营杠杆健康 |
20 ~ 50 | 放大明显,需验证成因 | 利润暴增,需确认是否为非经常性损益 |
> 50 | 异常·畸高放大 | 可能基数效应或数据异常,需人工复核 |
条件判断的顺序至关重要,必须从最特殊的区间(如<0)向一般区间递进,避免逻辑覆盖。
三、核心代码解析:三步构建诊断模型
第一步:自定义函数计算增长率
def calc_growth_rate(series):"""按行计算增长率。前提:数据已按时间从旧到新排序(第0行最旧,最后一行最新)增长率= (当期数 - 上期数) / |上期数| * 100%"""values = series.astype(float)growth_rates = []for i in range(len(values)): if i == 0: # 第一行(最早数据),无上期 growth_rates.append(None) else: current = values.iloc[i] # 当期 prev = values.iloc[i - 1] # 上期 if prev == 0 or pd.isna(prev): growth_rates.append(None) else: rate = (current - prev) / abs(prev) * 100 growth_rates.append(round(rate, 2))return growth_rates
关键设计点:
使用abs(prev) 作为分母,避免上期数为负时增长率符号混乱
第一行返回None,因为最早年份无"上期"可比
对零值和缺失值进行保护,防止除零错误
第二步:计算关系系数
df['营业收入增长率%'] = calc_growth_rate(df["营业收入"])df['净利润增长率%'] = calc_growth_rate(df["净利润"])df['关系系数'] = df['净利润增长率%'] / df['营业收入增长率%']
第三步:智能诊断备注
# 初始化备注列df['备注'] = ''# 按条件遍历赋值(从特殊到一般,顺序不能乱)for idx, row in df.iterrows(): coef = row['关系系数'] if pd.isna(coef): df.loc[idx, '备注'] = '数据缺失' continue if coef < 0: df.loc[idx, '备注'] = '异常·方向背离' elif 0 <= coef < 1: df.loc[idx, '备注'] = '杠杆失灵(费用上升)' elif 1 <= coef < 1.1: df.loc[idx, '备注'] = '杠杆失灵(弹性不足)' elif 1.1 <= coef <= 20: df.loc[idx, '备注'] = '正常(杠杆效应发挥)' elif 20 < coef <= 50: df.loc[idx, '备注'] = '放大明显,需验证成因' elif coef > 50: df.loc[idx, '备注'] = '异常·畸高放大' else: df.loc[idx, '备注'] = '—'
条件判断顺序的学问:
必须先判断pd.isna(coef),否则后续数值比较会报错;
必须先判断< 0,再判断 0 <= coef < 1,否则负数会被第一个非负区间"截胡";
区间边界采用左闭右开(如1 <= coef < 1.1),确保无遗漏无重叠;
四、实战演示:
读取指定上市公司数据——运行代码——自动计算增长率——自动计算关系系数——自动输出判断结论,如上表。
以上python代码是财务建模的核心代码块,学习者增加读取数据模块即可使用。当然,要确保表格字段与代码一致。
本文可作为《财务大数据分析(基于PYthon)》项目二强化python应用基础中任务五函数的自定义与调用;任务六循环与判断语句的应用课后学习材料。