中国高等院校教育资源区域分布分析研究
基于教育部 2024 年全国普通高等学校名单,通过数据采集、清洗、统计分析、机器学习聚类和可视化展示,系统性研究中国大陆高等教育资源的区域分布特征与均衡性。
项目背景
高等教育资源的区域分布直接影响教育公平与社会发展。本项目通过数据科学方法,量化分析我国高校资源的省际差异、区域特征、城市群集聚等关键问题,为教育政策制定提供数据支撑。
研究范围与数据口径
- 研究范围:中国大陆普通高等学校(不含港澳台)
- 数据源:教育部 2024 年全国普通高等学校名单
- 双一流:2022 年第二轮"双一流"建设高校名单
- 985/211:历史固定名单
- 人口数据:第七次全国人口普查(2020 年)
- 城市群:京津冀、长三角、粤港澳大湾区、成渝城市群
技术架构
核心技术栈
- Python 3.12 - 项目基础语言
- Pandas - 数据处理与分析
- Scikit-learn - 机器学习聚类
- Matplotlib + Seaborn - 数据可视化
- Openpyxl - Excel 文件处理
核心功能实现
1. 数据采集与爬取
实现教育部官网数据自动采集:
import requests
import pandas as pd
from openpyxl import load_workbook
class EducationDataCrawler:
def __init__(self):
self.base_url = "https://www.moe.gov.cn"
self.headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)'
}
def download_official_list(self):
response = requests.get(
f"{self.base_url}/jyb_xxgk/xxgk_content.html",
headers=self.headers
)
excel_url = self.extract_excel_url(response.text)
excel_data = requests.get(excel_url)
with open('data/raw/universities_raw.xlsx', 'wb') as f:
f.write(excel_data.content)
def parse_excel(self):
wb = load_workbook('data/raw/universities_raw.xlsx')
ws = wb.active
data = []
for row in ws.iter_rows(min_row=2, values_only=True):
data.append({
'name': row[0],
'province': row[1],
'city': row[2],
'level': row[3],
'authority': row[4],
'remark': row[5],
})
df = pd.DataFrame(data)
df.to_csv('data/raw/universities_raw.csv', index=False)
return df
2. 数据清洗与标准化
实现省份标准化、城市标准化、办学层次统一:
class DataCleaner:
def __init__(self):
self.province_mapping = self.load_province_mapping()
self.elite_universities = self.load_elite_list()
def clean_data(self, df: pd.DataFrame) -> pd.DataFrame:
df = df.copy()
df['province'] = df['province'].map(self.standardize_province)
df['city'] = df['city'].map(self.standardize_city)
df = df[~df['province'].isin(['香港', '澳门', '台湾'])]
df['level_standard'] = df['level'].apply(self.standardize_level)
df['ownership'] = df['authority'].apply(self.identify_ownership)
df['is_985'] = df['name'].isin(self.elite_universities['985'])
df['is_211'] = df['name'].isin(self.elite_universities['211'])
df['is_double_first_class'] = df['name'].isin(
self.elite_universities['double_first_class']
)
return df
def standardize_province(self, province: str) -> str:
return self.province_mapping.get(province, province)
def standardize_level(self, level: str) -> str:
if '本科' in level:
return '本科'
elif '专科' in level or '高职' in level:
return '高职专科'
return '其他'
def identify_ownership(self, authority: str) -> str:
if '民办' in authority or '民营' in authority:
return '民办'
return '公办'
3. 统计分析模块
生成省级、区域、城市、城市群多维度汇总:
class StatisticsAnalyzer:
def __init__(self, df: pd.DataFrame):
self.df = df
self.regions = self.load_region_mapping()
self.city_clusters = self.load_city_clusters()
def generate_province_summary(self) -> pd.DataFrame:
summary = self.df.groupby('province').agg({
'name': 'count',
'level_standard': lambda x: (x == '本科').sum(),
'ownership': lambda x: (x == '公办').sum(),
'is_985': 'sum',
'is_211': 'sum',
'is_double_first_class': 'sum',
}).rename(columns={
'name': 'total_universities',
'level_standard': 'undergraduate_count',
'ownership': 'public_count',
'is_985': '985_count',
'is_211': '211_count',
'is_double_first_class': 'double_first_class_count',
})
population = self.load_population_data()
summary['population'] = summary.index.map(population)
summary['per_million'] = (
summary['total_universities'] / summary['population'] * 1000000
)
return summary
def generate_region_summary(self) -> pd.DataFrame:
self.df['region'] = self.df['province'].map(self.regions)
return self.df.groupby('region').agg({
'name': 'count',
'level_standard': lambda x: (x == '本科').sum(),
'is_double_first_class': 'sum',
})
4. 均衡性指标计算
计算基尼系数、泰尔指数、HHI、变异系数:
import numpy as np
class InequalityMetrics:
def calculate_gini(self, data: np.ndarray) -> float:
sorted_data = np.sort(data)
n = len(data)
cumsum = np.cumsum(sorted_data)
gini = (2 * np.sum((np.arange(1, n + 1)) * sorted_data)) / (n * cumsum[-1]) - (n + 1) / n
return gini
def calculate_theil(self, data: np.ndarray) -> float:
mean_value = np.mean(data)
theil = np.sum((data / mean_value) * np.log(data / mean_value)) / len(data)
return theil
def calculate_hhi(self, data: np.ndarray) -> float:
shares = data / np.sum(data)
hhi = np.sum(shares ** 2)
return hhi
def calculate_cv(self, data: np.ndarray) -> float:
return np.std(data) / np.mean(data)
def calculate_lorenz_curve(self, data: np.ndarray) -> tuple:
sorted_data = np.sort(data)
cumsum = np.cumsum(sorted_data)
x = np.arange(1, len(data) + 1) / len(data)
y = cumsum / cumsum[-1]
return x, y
5. 机器学习聚类
KMeans 聚类 + PCA 降维可视化:
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
class MachineLearningAnalyzer:
def __init__(self, province_summary: pd.DataFrame):
self.data = province_summary
self.scaler = StandardScaler()
def prepare_features(self) -> pd.DataFrame:
features = self.data[[
'total_universities',
'undergraduate_count',
'double_first_class_count',
'per_million',
]]
features_scaled = self.scaler.fit_transform(features)
return pd.DataFrame(features_scaled, columns=features.columns)
def kmeans_clustering(self, n_clusters: int = 4):
features = self.prepare_features()
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
clusters = kmeans.fit_predict(features)
self.data['cluster'] = clusters
return self.data
def pca_visualization(self):
features = self.prepare_features()
pca = PCA(n_components=2)
pca_result = pca.fit_transform(features)
self.data['pca_1'] = pca_result[:, 0]
self.data['pca_2'] = pca_result[:, 1]
return self.data, pca.explained_variance_ratio_
6. 数据可视化
生成地图、柱状图、堆叠图、散点图、洛伦兹曲线:
import matplotlib.pyplot as plt
import seaborn as sns
class Visualizer:
def __init__(self, output_dir: str):
self.output_dir = output_dir
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
def plot_province_distribution(self, summary: pd.DataFrame):
fig, ax = plt.subplots(figsize=(14, 6))
summary = summary.sort_values('total_universities', ascending=False).head(20)
ax.bar(summary.index, summary['total_universities'])
ax.set_xlabel('省份')
ax.set_ylabel('高校数量')
ax.set_title('各省高校数量分布(Top 20)')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig(f'{self.output_dir}/province_distribution.png', dpi=300)
def plot_lorenz_curve(self, x: np.ndarray, y: np.ndarray, gini: float):
fig, ax = plt.subplots(figsize=(8, 8))
ax.plot([0, 1], [0, 1], 'k--', label='完全平等线')
ax.plot(x, y, 'b-', label=f'洛伦兹曲线 (Gini={gini:.3f})')
ax.fill_between(x, y, [0, 1], alpha=0.3)
ax.set_xlabel('累计省份比例')
ax.set_ylabel('累计高校数量比例')
ax.set_title('高校资源分布洛伦兹曲线')
ax.legend()
plt.tight_layout()
plt.savefig(f'{self.output_dir}/lorenz_curve.png', dpi=300)
def plot_cluster_result(self, data: pd.DataFrame):
fig, ax = plt.subplots(figsize=(10, 8))
scatter = ax.scatter(
data['pca_1'],
data['pca_2'],
c=data['cluster'],
cmap='viridis',
s=100,
alpha=0.6
)
for idx, row in data.iterrows():
ax.annotate(idx, (row['pca_1'], row['pca_2']))
ax.set_xlabel('主成分 1')
ax.set_ylabel('主成分 2')
ax.set_title('省级高校资源聚类结果(PCA降维)')
plt.colorbar(scatter, label='聚类')
plt.tight_layout()
plt.savefig(f'{self.output_dir}/cluster_pca.png', dpi=300)
研究发现
1. 高校数量省际分布
- 头部集中:江苏、广东、山东位居前三
- 地区差异:东部省份高校数量显著高于中西部
- 人均差异:北京、上海人均高校资源最丰富
2. 优质资源分布
- 双一流分布:北京、上海、江苏占据优势
- 985/211 集中:头部城市集聚效应明显
- 区域不均:东部地区优质资源占比超 60%
3. 均衡性指标
- 基尼系数:0.42(中等不均衡)
- 泰尔指数:显示区域内差异大于区域间差异
- 城市群集聚:京津冀、长三角高校密度最高
4. 机器学习聚类
识别出四类省份:
- 第一梯队:北京、江苏、上海(高校数量多 + 优质资源多)
- 第二梯队:广东、山东、湖北(高校数量多,优质资源中等)
- 第三梯队:河南、四川、湖南(高校数量中等)
- 第四梯队:西部省份(高校数量少,优质资源少)
技术挑战与解决方案
挑战 1:数据标准化
解决方案:构建省份、城市、办学层次映射表
挑战 2:多维度汇总
解决方案:pandas groupby + agg 实现灵活聚合
项目成果
- 完整的数据采集与清洗流程
- 36 个统计指标与可视化图表
- 机器学习聚类分析
- 完整的研究报告
技术启示
- 数据口径统一很重要:标准化是分析的基础
- 多维度分析更全面:省级、区域、城市群多角度
- 机器学习提供新视角:聚类发现隐藏模式
- 可视化是研究的重要支撑:图表让结论更直观
通过本项目,我系统掌握了数据科学研究的完整流程,从数据采集、清洗、统计分析到机器学习、可视化,每个环节都体现了严谨性与工程化思维。