ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

投入产出系数与模型实战:直接消耗系数、列昂惕夫逆矩阵、RAS与SDA

2026/9/18 21:49:43 拓冰建站 浏览量
投入产出系数与模型实战:直接消耗系数、列昂惕夫逆矩阵、RAS与SDA 简介这是一份面向经济学、统计学及数量经济方向学习者与教研人员的课件资料围绕投入产出系数与投入产出模型展开适合课堂教学、考前复习与实证建模入门参考。压缩包内共1个ppt文件整体约2.66MB以幻灯片形式呈现涵盖概念定义、公式推导、矩阵表示与实例演算便于逐页讲解与自学。内容从投入产出表的基本表式讲起梳理中间使用、最终使用、初始投入、固定资产折旧、劳动报酬与纯收入等分配去向重点说明直接消耗系数的定义、计算公式与性质并给出直接消耗系数矩阵A的排列方式随后推导完全消耗系数说明完全消耗等于直接消耗与各次间接消耗之和展示完全消耗系数矩阵B及矩阵运算求解过程。资料还配有假想的某国4部门价值型投入产出表以及1997年、2000年中国价值型投入产出表和1992年实物型投入产出表的部分消耗系数比较可帮助读者把公式与真实数据对应起来理解经济系统运行机制、结构关联与投资决策分析的基本思路。目前已有583人学习下载。1. 投入产出系数和投入产出模型.ppt课件里真正能跑起来的那部分很多人拿到一份叫《投入产出系数和投入产出模型.ppt》的课件习惯当讲义翻翻到直接消耗系数那一页抄个公式翻到列昂惕夫逆矩阵那一页抄个 (I-A)⁻¹然后关掉。真正耗时间的从来不是公式而是把年鉴里那张几十行几十列的投入产出表塞进这套公式的过程——部门口径对不齐、行合计和列合计差了几百亿、矩阵条件数大到求逆结果不可信、系数隔几年就过期。这篇按实际动手顺序写怎么从课件里把表格抽成结构化数据怎么算直接消耗系数和完全消耗系数怎么用 RAS 把旧系数外推到新年度最后用 SDA 把增长拆成技术变动和需求变动两块。适合自己做产业关联测算、成本传导估算、区域经济影响评估的工程和数据分析同学。2. 从投入产出表到直接消耗系数把 .ppt 里的表格变成可算的矩阵2.1 投入产出表的四个象限与数据落位投入产出表看起来是一张大表本质是四块。第一象限是部门×部门的中间使用流量记作 Z元素 z_ij 表示 j 部门生产过程中消耗 i 部门产品的数量。第二象限是部门×最终使用记作 Y包含消费、资本形成、出口这些列。第三象限是增加值×部门记作 V劳动者报酬、生产税净额、营业盈余都在这里。第四象限是增加值与最终使用的交叉一般不做分析。区块行列范围内容变量是否参与建模第一象限部门×部门中间使用流量Z (n×n)是核心第二象限部门×最终使用消费/资本形成/出口Y (n×k)是外生需求第三象限增加值×部门报酬/税收/盈余V (m×n)是约束校验第四象限增加值×最终使用再分配—一般忽略行方向Σ_j z_ij y_i X_ii 部门的总产出等于它被各部门中间消耗的部分加上最终使用。列方向Σ_i z_ij v_j X_jj 部门的总投入等于中间投入合计加增加值合计。这两条恒等式是所有后续计算的护栏任何一步算完都要回来核对。2.2 用 python-pptx 抽出课件里的表格python-pptx 只能读 .pptx遇到老的二进制 .ppt 先用 LibreOffice 无头模式转一次格式# 把二进制 ppt 转成 pptx输出到当前目录 soffice --headless --convert-to pptx 投入产出系数和投入产出模型.ppt转换后逐页找表格形状把单元格文本抠出来拼成 DataFramefrom pptx import Presentation import pandas as pd prs Presentation(投入产出系数和投入产出模型.pptx) frames {} for i, slide in enumerate(prs.slides, start1): for shape in slide.shapes: if not shape.has_table: # 只处理表格形状文本框跳过 continue tbl shape.table # 单元格里常带千分位逗号、全角空格、换行先清洗 rows [[c.text.strip().replace(,, ).replace(\u3000, ) for c in r.cells] for r in tbl.rows] df pd.DataFrame(rows[1:], columnsrows[0]) df df.set_index(df.columns[0]) # 第一列是部门名设成索引 frames[fslide{i}_{shape.shape_id}] df print(list(frames.keys()))has_table是形状级判断比按形状类型硬编码可靠。清洗那一步不能省年鉴导出的数字普遍带千分位全角空格会把pd.to_numeric直接打回 NaN。合并单元格会让同一段文字在多个 cell 里重复出现抽完要人工看一眼表头别指望自动对齐。抽出来的是字符串还要转数值并丢掉合计行def to_numeric(df): out df.apply(pd.to_numeric, errorscoerce) # 合计行、注释行的标签转数值后是 NaN整行整列丢 return out.dropna(howall).dropna(axis1, howall).astype(float) Z to_numeric(frames[slide3_5]).values # 中间流量矩阵 x to_numeric(frames[slide3_6]).values.reshape(-1) # 总投入列errorscoerce把不认识的文本变 NaN 而不是抛异常配合dropna才能一次清掉合计行。注意x要 reshape 成一位数组后面要按列做除法。2.3 直接消耗系数 a_ij 的计算与三条校验直接消耗系数就是列归一化a_ij z_ij / X_j含义是 j 部门每生产一单位总产出直接消耗 i 部门产品的数量。import numpy as np def direct_coefficients(Z, x): Z: 中间流量矩阵 (n,n)行消耗方列生产方 x: 总投入/总产出列向量 (n,) Z np.asarray(Z, dtypefloat) x np.asarray(x, dtypefloat).reshape(-1) assert Z.shape[0] Z.shape[1] x.size, 维度对不上先查表头 A Z / x[np.newaxis, :] # 按列除分母是 j 部门的总投入 return A A direct_coefficients(Z, x) # 校验一行模型平衡X 与 Ax Y 的差距应该在舍入误差量级 resid np.max(np.abs(A x Y.sum(axis1) - x) / x) print(行平衡最大相对误差:, resid) # 校验二中间投入率A 的列和必须落在 (0,1) colsum A.sum(axis0) print(中间投入率范围:, colsum.min(), colsum.max()) # 校验三系数不允许为负 print(负值个数:, int((A 0).sum()))x[np.newaxis, :]把列向量拉成 (1,n)触发广播实现按列除。分母用错的典型是把增加值当成了总投入那样列和会算出来大于 1。行平衡相对误差控制在 1e-6 以内说明搬数没搬错如果到 1e-2 级别多半是某个部门的最终使用列漏了出口或者存货变动。注意A 的行索引是「谁消耗」列索引是「谁生产」。建模全程带着部门名当 index 和 columns出问题时能一眼定位到是哪两个部门之间对不上比看下标快得多。3. 列昂惕夫逆矩阵与完全消耗系数np.linalg 之外的三个坑3.1 行模型推导与 (I-A) 可逆的条件把行平衡写成矩阵形式X A·X Y移项得 (I-A)·X Y于是 X (I-A)⁻¹·Y。这个逆矩阵就是列昂惕夫逆矩阵 L。(I-A)⁻¹ 还可以按级数展开成 I A A² A³ …A 是直接消耗A² 是经过一个中间环节的间接消耗A³ 是经过两个环节的累加起来就是完全消耗。可逆的前提是级数收敛对非负矩阵 A 来说就是谱半径 ρ(A) 1即最大特征值模长小于 1。实践中有一个更容易判断的充分条件A 的每一列之和都小于 1。列和就是中间投入率一个部门不可能把超过 100% 的产出都当中间投入用掉所以正常数据基本都满足。n A.shape[0] rho max(abs(np.linalg.eigvals(A))) print(谱半径:, rho, | 列和最大值:, A.sum(axis0).max()) assert rho 1, 谱半径不小于 1数据或口径有问题先别求逆3.2 用 numpy 求列昂惕夫逆矩阵def leontief_inverse(A): n A.shape[0] M np.eye(n) - A cond np.linalg.cond(M) print(cond(I-A) , cond) # 超过 1e10 基本不可信 if cond 1e10: raise ValueError(条件数过大检查是否有近乎重复的部门) L np.linalg.solve(M, np.eye(n)) # 解方程比直接 inv 数值更稳 return L L leontief_inverse(A) B L - np.eye(n) # 完全消耗系数 列昂惕夫逆 - I两个概念必须分清L 叫完全需要系数矩阵元素 l_ij 表示 j 部门每增加一单位最终使用i 部门需要提供的总产出含 j 自己那一份B L - I 才是完全消耗系数扣掉了自身那一单位表示直接加间接的消耗。做成本传导用 L做产业链拉动测算也常用 L别把两者混着报数。solve和inv的结果在数学上一样但inv内部也是解方程直接写solve(M, np.eye(n))少一次显式求逆条件数大时误差更可控。条件数这个数字值得每次都打出来它本质上是「部门之间耦合得太死」的量化指标接近 1e10 以上时求逆结果对输入数据的第四位小数都敏感。3.3 影响力系数与感应度系数的批量算法这两个系数是课件里出现频率最高、也最容易被问「大于 1 说明什么」的部分。影响力系数看列衡量 j 部门每增加一单位最终需求对全部部门的拉动强度感应度系数看行衡量各部门需求同时增加时i 部门被拉动得多厉害。def linkage(L, names): n L.shape[0] col L.sum(axis0) # 列和 - 影响力 row L.sum(axis1) # 行和 - 感应度 f col / col.mean() e row / row.mean() return pd.DataFrame({影响力系数: f, 感应度系数: e}, indexnames).round(4) print(linkage(L, dept_names).sort_values(影响力系数, ascendingFalse).head(10))系数方向公式判读影响力系数L 的列和Σ_i l_ij / (列和均值)1 拉动高于平均适合做需求刺激落点感应度系数L 的行和Σ_j l_ij / (行和均值)1 容易被需求带动也易成供给瓶颈两者都 1交叉—强关联部门冲击传导路径上的关键节点分母用的是列和或行和的算术平均所以全部部门的系数均值恒等于 1。这意味着别去比较绝对大小只比相对位次。想让结论稳一点可以分别用 L 和 B 各算一遍看排序是否一致两个口径下都排前五的部门通常可以直接写进报告。4. 系数会过期用 RAS 把旧投入产出表外推到新年度4.1 为什么要更新 A正规投入产出表按固定年份编制间隔好几年。等到要用的时候产业结构早就变了某些部门的中间投入率降了另一些升了。直接拿旧年的 A 去算新年的影响误差能吃掉整个结论。RAS 法是最常用的更新手段它假设技术系数的变动可以拆成两个方向行方向的「替代效应」——同样的投入品被别的部门产品替代列方向的「加工深度效应」——同样产出需要的中间投入总量变了。RAS 需要两组外部控制量目标年度各部门中间使用合计 u行和和各部门中间投入合计 v列和。这两个数一般从新年度的总产出和增加值反推u_i ≈ X_i − y_iv_j ≈ X_j − v_j(增加值)。4.2 RAS 迭代的实现与收敛判据def ras(A0, u, v, tol1e-8, max_iter1000): A0: 基年直接消耗系数 (n,n) u : 目标年行和各部门中间使用合计(n,) v : 目标年列和各部门中间投入合计(n,) A np.array(A0, dtypefloat) u np.asarray(u, dtypefloat) v np.asarray(v, dtypefloat) for k in range(1, max_iter 1): rs A.sum(axis1) r np.divide(u, rs, outnp.ones_like(u), wherers 0) # 行乘数 A r[:, None] * A cs A.sum(axis0) s np.divide(v, cs, outnp.ones_like(v), wherecs 0) # 列乘数 A A * s[None, :] err max(np.max(np.abs(A.sum(axis1) - u)), np.max(np.abs(A.sum(axis0) - v))) if err tol: break return A, k, err A_new, iters, err ras(A, u_new, v_new) print(f迭代 {iters} 次收敛最大误差 {err:.2e})wherers 0是防零行某些部门在基年完全没有某类中间使用直接除会出 inf。r 是行乘数也叫替代乘数s 是列乘数也叫加工乘数。最终 A_new diag(r)·A0·diag(s)这是 RAS 的闭式形式迭代只是求这两个向量的手段。一般几十次内收敛超过 500 次还没到 1e-8通常是 u 和 v 本身自相矛盾——比如两组控制量的总和差了百分之几那是数据问题不是算法问题。4.3 更新结果怎么验三条硬指标校验项公式期望行列和误差max(abs(rowsum−u), abs(colsum−v)) 1e-8系数偏离度mean(abs(A_new − A0))一般 0.005~0.05超过 0.1 要警惕位次稳定性影响力系数排序的斯皮尔曼相关大于 0.9 说明结构调整温和偏离度超过 0.1 时不要直接拿去用。先做一次对照把 u、v 换成基年自己的行列和跑一遍 RAS如果结果和 A0 不一样说明迭代实现或者控制量构造有错。位次稳定性用scipy.stats.spearmanr一行就能算排序大幅跳变的部门逐个回去查它的总产出和增加值数据。提示如果 RAS 怎么调都收敛不到目标可以退一步用 GRAS/最小交叉熵方法它允许部分控制量缺位代价是实现复杂度上升一个档次。绝大多数年度更新场景RAS 已经够用。5. 进阶用 SDA 拆解增长再把结果回写成一页 PPT系数更新完最有信息量的动作是做结构分解分析SDA把两个年份之间的总产出变化拆成「技术系数变了多少」和「最终需求变了多少」。用两极分解可以避免交叉项归属的随意性def sda_two_polar(L0, L1, Y0, Y1): L0/L1: 基年/目标年列昂惕夫逆矩阵 Y0/Y1: 基年/目标年最终使用列向量 dL L1 - L0 dY (Y1 - Y0).reshape(-1, 1) tech 0.5 * (dL ((Y0 Y1).reshape(-1, 1))) # 技术变动贡献 final 0.5 * ((L0 L1) dY) # 需求变动贡献 return tech.ravel(), final.ravel() tech, final sda_two_polar(L, L_new, Y.sum(axis1), Y_new.sum(axis1)) check np.max(np.abs((tech final) - (X_new - X))) print(分解残差:, check) # 应接近 0两极分解把交互项对半分给技术项和需求项tech final必然等于X_new - X残差只来自浮点误差。这一步的实用价值在于回答「某部门产出涨了 20%是它自己需求好还是上游技术变了」。如果final占七成以上说明是需求驱动属于景气问题如果tech占大头说明产业结构真变了旧系数不能再凑合。结果落地时直接用 python-pptx 生成一页汇报页比截图粘贴可控得多from pptx import Presentation from pptx.util import Inches, Pt prs Presentation() slide prs.slides.add_slide(prs.slide_layouts[5]) rows, cols len(dept_names) 1, 3 gt slide.shapes.add_table(rows, cols, Inches(0.5), Inches(1.2), Inches(9), Inches(0.3 * rows)).table gt.cell(0, 0).text, gt.cell(0, 1).text, gt.cell(0, 2).text 部门, 技术贡献, 需求贡献 for i, name in enumerate(dept_names, start1): gt.cell(i, 0).text name gt.cell(i, 1).text f{tech[i-1]:.1f} gt.cell(i, 2).text f{final[i-1]:.1f} for c in range(3): gt.cell(i, c).text_frame.paragraphs[0].font.size Pt(10) prs.save(sda_result.pptx)一个容易忽略的细节表格行高按0.3 * rows估算超过 20 个部门就得拆成两页否则字号会被自动压到看不清。另外把dept_names和三个数值列一起落成 CSV 再用pd.read_csv(..., index_col0)读回下一轮更新时就不用重新对表头——部门口径是这套流程里最容易漂移的东西固定住它对结果复现的帮助比任何算法优化都大。本文还有配套的精品资源点击获取