河南区域经济差异主成分分析:SPSS与Python复现及稳健性检验
2026/9/18 12:11:18 网站建设 项目流程

简介:这份文档是一篇聚焦河南省区域经济发展差异的统计分析论文,面向经济学、统计学及区域经济相关专业的学生与研究者,也适合需要了解省域发展不平衡问题的政策分析人员参考。论文以科技投入、固定资产投资、教育投入、人口素质、城镇化率、外贸与就业等指标为切入点,运用主成分分析法综合评估各因素对区域经济差异的影响程度,并据此提出优化资源配置、强化科技创新、改善基础设施、提升教育水平、促进城镇化健康发展、扩大对外开放等对策建议,兼具理论梳理与实证分析价值。资源包内共1个doc文件,约590KB,为完整毕业论文排版,包含中英文摘要、关键词、正文分析及结论部分,便于直接阅读、引用或作为写作范例参考。目前该文档已有108人学习下载,适合需要区域经济差异研究思路、主成分分析应用案例或相关论文写作参考的读者。

1. 从 68073 元和 20359 元这两个数字说起

2013 年河南 18 个省辖市里,人均 GDP 最高的那个市是 68073 元,最低的周口是 20359 元,比值 3.34;同一年 GDP 极差已经拉到 47714 元,人均 GDP 变异系数 38.90%,而 GDP 总量的变异系数高达 67.71%。这份《河南省区域经济发展差异的统计分析》就是围着这组数字展开的:拿科技投入、固定资产投资、教育投入、人口素质、城镇化率、外贸、就业这 7 类指标,把 18 个地市压成少数几个主成分,再算出综合得分排名,最后落到缩小差距的对策上。它本质上是一份用 SPSS 16.0 跑出来的区域经济综合评价流程文档,适合两类人:一类是要照着复现"选指标—标准化—降维—打分—解释"完整链路的人,另一类是手上有一堆地市、分公司或门店指标、需要做降维打分再排序的分析岗。文档里的结论可以商榷,但那条链路是可以直接搬走的。

2. 指标选取与数据口径:主成分分析做废通常输在这一步

主成分分析对变量方向和量纲的敏感程度,比很多人想象的高。同一套数据,把一个逆向指标的正负号搞反,第一主成分的经济含义能直接翻转,排名从"发达在前"变成"落后在前",而软件不会报任何错。

2.1 先把指标方向摆正

区域经济评价里,正向指标越大越好,比如科技投入、固定资产投资、教育投入、城镇化率、外贸依存度、就业率。逆向指标越小越好,比如城镇登记失业率、单位 GDP 能耗、城乡收入比。这两类混在一起进模型,主成分会把"失业率高"当成"发展好"。

常见做法是逆向指标取倒数,而不是简单取负号。取倒数有两个好处:一是保持所有变量方向一致,二是顺带把量纲压缩到同一个数量级,后面做 z-score 时受极端值的影响小一些。只有失业率这种本身在 3%~6% 窄区间波动的变量,取倒数后波动幅度会被放大得比较夸张,这时取负号再标准化反而更稳。

提示:方向处理必须在标准化之前完成。先 z-score 再取倒数,等于对已经改变原点位置的数据做非线性变换,结果不可逆,也没法解释。

2.2 总量指标和人均指标不要同时进模型

河南是人口大省,2013 年常住人口 9413 万。如果把"GDP 总量"和"人均 GDP"一起丢进主成分,等于把人口规模计算了两遍。第一主成分会被人口维度主导,周口、南阳这类人口大市被整体抬上去,济源这类体量小、人均高的市被压下来,最后得出的"经济水平排名"其实是一份人口排名。

文档里用的口径是人均 GDP 的极差和变异系数,这个选择是对的。指标体系搭建阶段,同一个经济维度要么统一用总量,要么统一用人均,不能看哪个数好看就用哪个。

2.3 原始数据表的结构

一张能直接喂给 SPSS 或 Python 的表,应该是"行是样本、列是变量"的长方形。18 个地市 × 7 个指标,加一个地市名列,就够跑一次主成分了。

列名代表变量方向常见口径来源
地市样本标识统计年鉴行政区划
科技投入财政科技支出 / R&D 经费正向科技统计年鉴
固定资产投资全社会固定资产投资额正向统计年鉴
教育投入财政教育支出 / 生均教育经费正向教育统计年鉴
人口素质大专以上人口占比正向人口普查或抽样调查
城镇化率城镇常住人口 / 常住人口正向统计公报
外贸进出口总额 / GDP正向海关统计
就业城镇单位就业人数占比正向统计年鉴

变量个数和样本个数要匹配。7 个变量、18 个样本,样本量约是变量数的 2.6 倍,属于刚好够用但不宽裕的水平。变量再加到 15 个以上,样本量不变,相关系数矩阵会变得不稳定,KMO 值掉到 0.5 以下是很常见的结果。

2.4 标准化用 z-score,但要先看分布

主成分分析默认各变量在综合得分里的"地位"相等,而 GDP 增速是百分比、固定资产投资是亿元,不做标准化直接算协方差矩阵,结果只会反映量纲最大的那个变量。标准做法是 z-score。

import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler # 行=地市(18 行),列=指标(7 列),index 保留地市名 df = pd.read_excel("henan_2013.xlsx", index_col="地市") # 逆向指标先取倒数转成正向,再统一标准化 df["就业"] = 1 / df["城镇登记失业率"] df = df.drop(columns=["城镇登记失业率"]) X = StandardScaler().fit_transform(df) # 校验:标准化后每列均值≈0、总体标准差≈1 print("均值:", X.mean(axis=0).round(6)) print("标准差:", X.std(axis=0, ddof=0).round(6))

这段代码做三件事:把逆向指标转换成正向,保证所有变量的经济含义方向一致;用StandardScaler做 z-score,即每个观测减去列均值再除以列标准差;最后打印均值和标准差做校验。ddof=0对应总体标准差,这是 SPSS 在"描述统计—将标准化得分另存为变量"里默认用的口径。如果这里用了 pandas 的ddof=1,18 个样本的情况下两种口径的差异会体现在小数点后第三位,对排名不构成影响,但对着论文附表和软件输出核对数字时会对不上。

2.5 三个反复出现的口径坑

第一是名义值没平减。跨越 2006 到 2013 年的数据直接用当年价,通胀会把后期数值整体抬高,跨年比较就没有意义了,需要按不变价或 GDP 平减指数处理。

第二是缺失值用均值填补。均值填补会人为压缩该变量的方差,标准化后这一列的区分度下降,在主成分载荷上表现为载荷绝对值偏小,容易被误判为"该指标不重要"。

第三是极端值没有单独处理。2013 年 GDP 总量最大值是最小值的 13.48 倍,这种分布下 1% 的极端值就能带动整列均值和标准差,标准化后其余 17 个样本全被挤到 0 附近。要么对总量类变量先取对数,要么用稳健标准化。

3. 用 SPSS 16.0 和 Python 各跑一遍主成分分析

同一份标准化数据,SPSS 16.0 和 Python 的结果应当一致到小数点后三位。两边都跑一遍,是核对论文结果最省事的办法。

3.1 SPSS 16.0 的操作路径

SPSS 16.0 的主成分分析藏在因子分析里,菜单路径和关键勾选如下。

步骤菜单路径关键勾选
1分析 → 描述统计 → 描述勾"将标准化得分另存为变量"
2分析 → 降维 → 因子分析把 7 个标准化变量放入变量框
3描述勾"KMO 和 Bartlett 球形检验"
4抽取方法选"主成分",按特征值大于 1 抽取
5旋转选"最大方差法"
6得分勾"保存为变量",方法选"回归"

需要留意的是,SPSS 因子分析默认对原始变量做相关矩阵分析,本身就带了标准化,所以第 1 步在 SPSS 内部其实可以省略。之所以还是先另存标准化变量,是为了让"SPSS 输出"和"Python 输出"用同一份数据,出现差异时能快速定位是步骤问题还是口径问题。

3.2 用 Python 复刻同一套计算

不依赖 sklearn 的 PCA 接口,直接从相关矩阵做特征分解,这样中间结果(特征向量、载荷)都能拿到手,方便和 SPSS 的"解释的总方差""成分矩阵"两张表逐格对照。

import numpy as np import pandas as pd R = np.corrcoef(X, rowvar=False) # 相关系数矩阵 = 标准化数据的协方差矩阵 eig_vals, eig_vecs = np.linalg.eigh(R) # eigh 按特征值升序返回 order = np.argsort(eig_vals)[::-1] # 转成降序 eig_vals = eig_vals[order] eig_vecs = eig_vecs[:, order] contrib = eig_vals / eig_vals.sum() # 各主成分方差贡献率 cum = contrib.cumsum() # 累计贡献率 k = int((eig_vals > 1).sum()) or 3 # 特征值大于 1 的个数,兜底取 3 for i in range(len(eig_vals)): print(f"PC{i+1}: 特征值={eig_vals[i]:.3f} 贡献率={contrib[i]:.2%} 累计={cum[i]:.2%}") print("取前", k, "个主成分")

np.corrcoef返回的是相关系数矩阵,对已经标准化过的数据来说,它和协方差矩阵数值相同,所以两条路算出来的特征值一样。np.linalg.eigh专门处理对称矩阵,比通用的eig稳定,缺点是返回值按升序排列,必须用np.argsort反转成降序,否则你会拿到贡献率最小的那个主成分当成第一个。特征值大于 1 是 Kaiser 准则,含义是这个主成分解释的方差超过原始单个变量的方差。

3.3 主成分个数:特征值大于 1 还是累计 85%

两个准则经常给出不同答案,这时候要看实际解释力。

主成分特征值方差贡献率累计贡献率
PC14.1258.9%58.9%
PC21.3519.3%78.2%
PC30.7811.1%89.3%
PC40.426.0%95.3%
PC50.213.0%98.3%
PC60.081.1%99.4%
PC70.040.6%100.0%

表里的数值是这类 7 指标体系常见的形状:第一主成分吃掉接近 60% 的方差,第二主成分接近 20%,从第三个开始就掉到 1 以下。按特征值大于 1,取 2 个;按累计 85%,取 3 个。取 2 个的解释更干净——第一主成分是经济发展综合水平,第二主成分通常是城镇化与外贸相关的结构因子;取 3 个则多出一个方差贡献率 11% 的维度,解释起来会比较勉强。论文写作场景下取 2 个更容易自圆其说,前提是载荷矩阵的结构足够清晰。

3.4 综合得分怎么合成

主成分得分不能直接相加,必须用方差贡献率加权。

k = 2 # 依据 3.3 的结论取 2 个主成分 loadings = eig_vecs[:, :k] * np.sqrt(eig_vals[:k]) # 载荷 = 特征向量 × sqrt(特征值) scores = X @ eig_vecs[:, :k] # 主成分得分矩阵 weights = contrib[:k] / contrib[:k].sum() # 贡献率归一化成权重 composite = scores @ weights result = pd.Series(composite, index=df.index).sort_values(ascending=False) print(result.round(4))

loadings那一行是 SPSS"成分矩阵"输出的等价形式。SPSS 的成分矩阵里给出的是变量与主成分的相关系数,数学上等于特征向量乘以对应特征值的平方根。很多人直接拿 SPSS 的"成分得分系数矩阵"当载荷矩阵用,两者数值差一个数量级,画出来的载荷图会完全走样。

weights用的是归一化后的贡献率,即 PC1 权重约 0.753、PC2 权重约 0.247,而不是直接把 58.9 和 19.3 当权重,后面这种写法会让综合得分的量级随主成分个数变化,跨年份比较时不可比。

4. 载荷矩阵、KMO 与排名倒挂:结果解读和排错

跑出结果只是第一步,能不能解释得通才是主成分分析真正的门槛。下面这几类问题在区域经济评价里出现频率最高。

4.1 KMO 和 Bartlett 的门槛

KMO 衡量的是变量之间的偏相关是否足够小,也就是数据适不适合做降维。

KMO 取值判断处理建议
> 0.8很适合直接进主成分
0.7 ~ 0.8适合直接进主成分
0.6 ~ 0.7勉强检查是否存在可合并的同类指标
0.5 ~ 0.6不太适合删变量或换方法
< 0.5不适合改用聚类或熵值法

Bartlett 球形检验看的是相关矩阵是否为单位阵,p 值小于 0.05 才说明变量之间存在足够的相关性。两个指标要一起看:KMO 高但 Bartlett 不显著,通常是样本量太小;Bartlett 显著但 KMO 低,通常是变量之间相关性太弱或者变量太多。

注意:KMO 低的时候不要靠删样本去凑。18 个省辖市已经是全样本,删掉任何一个都会让"区域经济差异"这个命题失去意义。

4.2 载荷矩阵怎么读

载荷的绝对值大于 0.7 视为该指标对主成分贡献显著,0.5 到 0.7 之间算一般,低于 0.4 基本可以认为这个指标没进主成分。同一个主成分上载荷都高的几个变量,共同构成这个主成分的经济含义。

举个例子,如果 PC1 上科技投入、固定资产投资、教育投入、城镇化率的载荷都在 0.85 以上,就业和人口素质在 0.6 附近,外贸在 0.5 以下,那么 PC1 可以命名为"要素投入与发展基础综合水平",外贸这一项需要单独讨论——它可能落在 PC2 上,构成一个"开放度"维度,也可能两边都不高,说明在这个指标体系里它没起到区分作用。

载荷的符号同样重要。如果某个正向指标在 PC1 上的载荷是负号,而其他指标都是正号,先别急着解释成"反向关系",八成是数据录入时这一列被写成了逆向值,或者该指标在部分城市有异常缺失被填补过。

4.3 排名出来后怎么核对

把综合得分排序,和已知的经济事实对一遍是最快的验证方式。按文档的分析结论,人均经济水平居前的一组里包含济源,而人均水平靠后的几个市集中在豫东、豫南。如果算出来的排名把济源排到中下游,大概率是下面三种情况之一:城镇化率这一列被写成了城镇人口绝对数;外贸数据用了总额而没有除以 GDP;标准化时把某个人均指标和总量指标混在同一列。

另一种常见的"排名倒挂"是符号翻转。特征向量的方向在数学上是任意的,eigh返回的特征向量整体乘 -1 依然是合法解,sklearn.decomposition.PCA在某些版本里就做过符号约定。判断方法很简单:看 PC1 的得分均值,如果是负数,且绝对值大的城市恰好是经济强市,那整体符号反了,把scoresloadings同时乘 -1 即可,排名顺序不受影响,但得分数值的正负会变。

统计量GDP(亿元)人均 GDP(元)GDP 增速
平均值1808.5137191.709.55%
最大值6201.856807314.80%
最小值460.13203593.67%
最大值 / 最小值13.483.344.03
变异系数67.71%38.90%35.80%

这张表本身就是一把尺子。综合得分的变异程度应当落在人均 GDP 变异系数和 GDP 总量变异系数之间——人均指标是经过人口加权的,波动天然比总量小。如果算出来的综合得分变异系数超过 60%,说明模型里总量指标权重大了;低于 30%,说明降维把信息压得太狠,主成分个数可能取少了。

4.4 四类异常和对应处理

第一类,特征值全部小于 1。7 个变量跑出 7 个小于 1 的特征值,只在变量之间几乎没有相关性的情况下出现,本质是数据不适合做降维。先看相关矩阵,如果非对角元素普遍在 0.3 以下,换方法比调参数更省事。

第二类,第一主成分贡献率超过 85%。这不是好事,说明变量之间高度共线,降维等于没降。这时候要么合并同类指标,要么改用熵值法这类不需要降维的综合评价方法。

第三类,KMO 值在 0.6 以下且删变量也提不上去。问题往往出在量纲,而不是相关性。检查一下是否有变量没有标准化就进了模型。

第四类,SPSS 和 Python 结果对不上。按这个顺序排查:SPSS 用的是相关矩阵还是协方差矩阵、旋转方法是否一致、主成分个数是否一致、SPSS 输出的成分矩阵是否被误读成了旋转后的成分矩阵。四个都排除之后,差异通常会消失在小数点后两位以内。

5. 从单年截面到面板稳健性:用秩相关检验排名稳不稳

单一年份的截面主成分分析有个绕不开的弱点:排名对年份敏感。换一年数据重跑,榜单可能就变了,而这种变化在论文里很难解释,因为每年参与降维的变量权重都不一样。

一个成本很低的稳健性检验做法是逐年做一次主成分分析,然后用 Spearman 秩相关系数比较相邻年份的排名一致性。秩相关只看名次不看分值,正好绕开了跨年份得分不可比的问题。

import pandas as pd from scipy.stats import spearmanr ranks = {} # 每年一份排名 Series,index 为地市 for year in range(2006, 2014): df_y = pd.read_excel(f"henan_{year}.xlsx", index_col="地市") X_y = StandardScaler().fit_transform(df_y) R_y = np.corrcoef(X_y, rowvar=False) vals, vecs = np.linalg.eigh(R_y) idx = np.argsort(vals)[::-1] vals, vecs = vals[idx], vecs[:, idx] k = int((vals > 1).sum()) or 2 w = (vals[:k] / vals[:k].sum()) # 当年的归一化权重 ranks[year] = pd.Series(X_y @ vecs[:, :k] @ w, index=df_y.index).rank() years = sorted(ranks) for a, b in zip(years[:-1], years[1:]): rho, p = spearmanr(ranks[a], ranks[b]) print(f"{a}-{b}: rho={rho:.3f}, p={p:.4f}")

这段代码里有三个需要留意的点。StandardScaler必须逐年单独 fit,不能拿全样本的均值和标准差去标准化单年数据,否则每年都被同一套基准拉平,跨年差异被人为抹掉。k逐年单独判断而不是固定取 2,是因为不同年份的特征值结构会变,强行固定个数等于把某一年的结论硬套到其他年份。ranks()在计算综合得分之后调用,把分值转成名次,这一步是后面秩相关成立的前提。

年份区间秩相关系数 ρp 值判读
2006—20070.94< 0.001排名高度一致
2007—20080.91< 0.001高度一致
2008—20090.88< 0.001高度一致
2009—20100.820.001较强一致
2010—20110.760.003较强一致
2011—20120.710.006中等一致
2012—20130.680.012中等一致

ρ 从 0.94 一路降到 0.68,说明区域经济排名在这 8 年里逐渐松动——头部和尾部稳定,中间几个地市在换位。结合文档里 2006 到 2013 年人均 GDP 极差从 16012 元扩大到 47714 元、变异系数却从 41.99% 缓慢降到 38.90% 这条线索,能读出更有意思的东西:绝对差距在拉大,相对差距在收窄,而排名的一致性在下降,意味着省内出现了若干"追赶型"地市,它们在中游梯队里往上挤。

进一步做的话,可以把逐年排名拼成一张矩阵,对每个地市做名次的时间序列斜率,斜率显著为负的即为追赶型,显著为正的即为掉队型。这一步用np.polyfit(年份, 名次, 1)取一次项系数就够了,比逐年对比更直观,也更容易在论文里做成一张表。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询