使用Pandas分析真实数据:从零开始的完整实践教程
在上一篇内容中,我们已经成功配置了Python数据分析的基础环境(包括Anaconda、Pandas与Matplotlib)。本文将在此基础上,借助一个真实的公开数据集,系统性地展示数据分析的全过程——涵盖数据读取、清洗、探索性分析到结果保存。通过本指南,你将掌握Pandas在实际项目中的核心应用方法。
所用数据集说明:美国社区调查简化版
本次分析采用的是来自美国人口普查局发布的社区调查数据(经过简化处理),该数据集融合了丰富的社会人口学信息和经济指标,适用于初学者进行实战演练。
主要字段包括:
- 年龄(age)
- 教育程度(education)
- 婚姻状态(marital_status)
- 性别(sex)
- 种族(race)
- 每周工作时长(hours_per_week)
- 收入水平(income),以是否超过50K美元为二分类标准
数据规模:约32,561条记录,共14个变量。
典型用途:适合用于演示数据预处理、分组聚合、特征间关系挖掘等常见分析任务。
完整操作流程(含可执行代码)
1. 环境初始化与数据导入
首先加载必要的库,并从网络地址获取数据文件,随后对数据结构进行初步查看,以便快速理解其组成。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 设置图形显示参数,确保中文正常渲染(兼容多操作系统)
plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Zen Hei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False # 避免负号显示异常
# 直接通过URL读取GitHub上的公开数据(无需手动下载)
url = "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/census.csv"
df = pd.read_csv(url)
# 1. 输出数据维度信息
print("=== 数据集基础信息 ===")
print(f"数据形状(行数×列数): {df.shape}")
# 2. 展示前五条数据,帮助理解各字段含义及格式
print("\n=== 前5行数据预览 ===")
print(df.head())
# 3. 查看每列的数据类型和非空值数量,评估是否存在缺失问题
print("\n=== 字段信息详情 ===")
print(df.info())
# 4. 对数值型变量生成统计摘要(均值、标准差、极值等)
print("\n=== 数值型字段统计摘要 ===")
print(df.describe().round(2)) # 保留两位小数提升可读性
[此处为图片1]
关键输出解读
- shape:反映整体数据量大小,例如输出
(32561, 14)表示共有三万余条记录和14个字段。 - info():重点关注“Non-Null Count”列判断是否有缺失,“Dtype”列确认字段类型是否正确。
- describe():仅作用于数值列,可用于识别潜在异常值(如年龄出现负数或超过150岁的情况)。
2. 数据清洗 —— 分析前的关键步骤
现实世界的数据通常存在缺失、重复或格式不一致的问题,必须先进行清理才能保证后续分析的有效性和准确性。
# 1. 统计每个字段的缺失情况
print("=== 各字段缺失值统计 ===")
missing_info = df.isnull().sum()
missing_rate = (df.isnull().sum() / len(df) * 100).round(2)
missing_df = pd.DataFrame({
'缺失值数量': missing_info,
'缺失率(%)': missing_rate
}).query('缺失值数量 > 0') # 仅显示含有缺失的字段
print(missing_df if not missing_df.empty else "无缺失值")
# 2. 根据缺失比例选择处理方式
# 若缺失率低于5%,可直接删除对应行
df_clean = df.dropna()
# 可选策略:若缺失较多,则考虑填充
# 例如分类变量使用众数填充:df['education'].fillna(df['education'].mode()[0], inplace=True)
# 数值变量可用均值代替:df['age'].fillna(df['age'].mean(), inplace=True)
# 3. 检测并移除重复记录
duplicate_count = df_clean.duplicated().sum()
print(f"\n=== 重复值处理 ===")
[此处为图片2]
上述过程完成后,我们将获得一份干净、结构清晰且可用于进一步分析的数据集。接下来即可开展诸如分组统计、可视化探索、相关性分析等工作。
# 数据清洗前重复行数量统计
print(f"清洗前重复行数量: {duplicate_count}")
df_clean = df_clean.drop_duplicates() # 去除完全重复的数据行
# 清洗后数据质量验证
print(f"清洗后数据形状: {df_clean.shape}")
print(f"清洗后缺失值数量: {df_clean.isnull().sum().sum()}")
print(f"清洗后重复值数量: {df_clean.duplicated().sum()}")
[此处为图片1]
数据清洗核心原则说明:
- 缺失值处理:若字段缺失率较低(小于5%),可直接删除对应记录;若缺失比例较高,则建议采用填充策略,避免样本量大幅减少。
- 重复值处理:对于完全一致的重复行,可安全删除,不影响后续数据分析结果。
- 异常值处理:当前阶段暂不处理,可在后续分析中通过可视化手段(如箱线图)识别并决策处理方式,适合进阶操作。
深入数据探索:解析变量分布特征
将变量划分为「分类变量」与「数值变量」两类,分别进行统计分析,以揭示数据内在结构与规律。一、分类变量分析(涵盖教育程度、婚姻状态、性别、种族、收入等非数值型字段)
categorical_cols = ['education', 'marital_status', 'relationship', 'sex', 'race', 'income'] print("=== 分类变量分布分析 ===") for col in categorical_cols: if col in df_clean.columns: print(f"\n【{col}】字段分布:") dist_count = df_clean[col].value_counts() dist_pct = (df_clean[col].value_counts(normalize=True) * 100).round(2) dist_df = pd.DataFrame({ '数量': dist_count, '占比(%)': dist_pct }) print(dist_df) print("-" * 60) [此处为图片3]二、数值变量分析(包括年龄、受教育年限、每周工作时长等连续型变量)
numeric_cols = ['age', 'education_num', 'hours_per_week'] print("\n=== 数值变量统计分析 ===") for col in numeric_cols: if col in df_clean.columns: print(f"\n【{col}】字段统计:") print(f" 均值: {df_clean[col].mean():.2f}") print(f" 中位数: {df_clean[col].median():.2f}") print(f" 标准差: {df_clean[col].std():.2f}") # 衡量数据波动性 print(f" 最小值: {df_clean[col].min()}") print(f" 最大值: {df_clean[col].max()}") print("-" * 60) [此处为图片4] 探索性分析结论解读:- 分类变量:重点关注各类别中的主导群体。例如,收入低于等于50K的人群占比是否占据多数,反映整体收入水平分布。
- 数值变量:通过比较均值与中位数判断分布形态——两者接近表明数据近似对称(可能符合正态分布);标准差大小反映离散程度,如“工作时长”标准差较大,说明个体间工作强度差异显著。
分组与聚合分析:挖掘不同类别间的差异性
利用分组聚合技术,探究不同分组(如教育背景、性别)在关键指标(如收入水平、工作时间)上的表现差异。1. 教育水平对收入的影响分析
(核心业务问题:更高的学历是否更有可能获得高收入?) if 'education' in df_clean.columns and 'income' in df_clean.columns: print("=== 教育水平与收入关系分析 ===") income_by_edu = df_clean.groupby('education')['income'].apply( lambda x: (x == '>50K').mean() * 100 ).round(2).sort_values(ascending=False) income_by_edu = pd.DataFrame(income_by_edu, columns=['高收入占比(%)']) print("各教育水平高收入占比(Top10):") print(income_by_edu.head(10)) [此处为图片5]2. 性别与工作时长的关系分析
(核心研究问题:不同性别的工作强度是否存在明显差异?) if 'sex' in df_clean.columns and 'hours_per_week' in df_clean.columns: print("\n=== 性别与工作时长关系分析 ===")
# 工作时长按性别分组统计
hours_by_sex = df_clean.groupby('sex')['hours_per_week'].agg([
'count', 'mean', 'median', 'std'
]).round(2)
hours_by_sex.columns = ['样本数', '平均工作时长', '中位数工作时长', '标准差']
print(hours_by_sex)
[此处为图片1]
年龄区间与收入水平关联分析
为进一步挖掘人口特征对收入的影响,若数据集中包含“age”与“income”字段,则进行如下处理:
if 'age' in df_clean.columns and 'income' in df_clean.columns:
print("\n=== 年龄分组与收入关系分析 ===")
# 划分年龄群体:青年(0-29)、中年(30-59)、老年(60+)
df_clean['age_group'] = pd.cut(
df_clean['age'],
bins=[0, 29, 59, 100],
labels=['青年(0-29)', '中年(30-59)', '老年(60+)']
)
# 计算各年龄段中高收入(>50K)的比例
income_by_age = df_clean.groupby('age_group')['income'].apply(
lambda x: (x == '>50K').mean() * 100
).round(2)
income_by_age = pd.DataFrame(income_by_age, columns=['高收入占比(%)'])
print(income_by_age)
[此处为图片2]
分组分析的意义与应用价值
- 将整体数据划分为不同子群体,有助于揭示潜在模式。例如,中年群体的高收入比例明显高于青年群体。
- 此类细分可为实际决策提供支持,如在招聘策略中优先考虑具备特定教育背景的候选人,因其更可能获得高收入。
数据可视化:提升洞察效率的关键手段
图表能更直观地展现数据趋势和变量间的关系。以下构建四个关键图表,涵盖分布、对比与关联分析,并采用2×2子图布局统一展示。
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
fig.suptitle('美国社区调查数据核心分析图表', fontsize=16, fontweight='bold')
# 图一:年龄分布直方图(观察整体年龄结构)
if 'age' in df_clean.columns:
axes[0, 0].hist(df_clean['age'], bins=30, alpha=0.8, color='#2E86AB', edgecolor='white', linewidth=0.8)
axes[0, 0].set_xlabel('年龄', fontsize=12)
axes[0, 0].set_ylabel('人数', fontsize=12)
axes[0, 0].set_title('年龄分布趋势', fontsize=14, fontweight='bold')
axes[0, 0].grid(axis='y', alpha=0.3) # 启用Y轴网格线以增强可读性
[此处为图片3]
# 图二:教育程度与高收入关联(横向条形图优化标签展示)
if 'education' in df_clean.columns and 'income' in df_clean.columns:
top_edu = df_clean['education'].value_counts().head(8).index
edu_income = df_clean[df_clean['education'].isin(top_edu)].groupby('education')['income'].apply(
lambda x: (x == '>50K').mean() * 100
).sort_values() # 按值升序排列,适配横条图阅读习惯
axes[0, 1].barh(range(len(edu_income)), edu_income.values, color='#A23B72', alpha=0.8)
axes[0, 1].set_yticks(range(len(edu_income)))
axes[0, 1].set_yticklabels(edu_income.index, fontsize=10)
axes[0, 1].set_xlabel('高收入占比(%)', fontsize=12)
axes[0, 1].set_title('Top8教育水平高收入占比', fontsize=14, fontweight='bold')
axes[0, 1].grid(axis='x', alpha=0.3)
[此处为图片4]
# 图三:性别与周工作时长分布对比(箱线图呈现离散情况)
# 检查是否存在性别与每周工作时长字段
if 'sex' in df_clean.columns and 'hours_per_week' in df_clean.columns:
# 构建箱线图所需数据
male_hours = df_clean[df_clean['sex'] == 'Male']['hours_per_week']
female_hours = df_clean[df_clean['sex'] == 'Female']['hours_per_week']
bp = axes[1, 0].boxplot([male_hours, female_hours], labels=['男性', '女性'],
patch_artist=True, notch=True)
# 配置箱体颜色与透明度
colors = ['#F18F01', '#C73E1D']
for patch, color in zip(bp['boxes'], colors):
patch.set_facecolor(color)
patch.set_alpha(0.7)
axes[1, 0].set_xlabel('性别', fontsize=12)
axes[1, 0].set_ylabel('每周工作时长(小时)', fontsize=12)
axes[1, 0].set_title('不同性别的工作时长分布', fontsize=14, fontweight='bold')
axes[1, 0].grid(axis='y', alpha=0.3)
# 收入结构的饼状图绘制
if 'income' in df_clean.columns:
income_counts = df_clean['income'].value_counts()
colors = ['#3F88C5', '#F9C74F']
wedges, texts, autotexts = axes[1, 1].pie(
income_counts.values, labels=income_counts.index, autopct='%1.1f%%',
startangle=90, colors=colors, textprops={'fontsize': 11}
)
# 添加边框以增强视觉效果
wedges[0].set_edgecolor('white')
wedges[1].set_edgecolor('white')
axes[1, 1].set_title('收入分布占比', fontsize=14, fontweight='bold')
# 自动调整布局防止标签重叠
plt.tight_layout()
# 输出高清图像文件
plt.savefig('census_analysis_charts.png', dpi=300, bbox_inches='tight')
plt.show()
print("图表已保存为 'census_analysis_charts.png'")
可视化方法说明
- 直方图:适用于呈现连续变量的分布特征,例如年龄主要集中于20至50岁区间。
- 条形图:用于比较不同分类之间的数值差异,如各教育水平下高收入人群的比例。
- 箱线图:可有效展示数据的离散程度及异常值情况,例如男性群体的工作时长中位数相对更高。
- 饼图:适合表达类别在整体中的占比关系,比如高收入者约占总样本的24%。
6. 进阶分析:变量间相关性探究
通过分析数值型变量之间的线性关联,识别潜在的影响因素及其相互作用。
# 第一步:提取所有数值类型列(排除非数值的分类字段)
numeric_df = df_clean.select_dtypes(include=[np.number])
print("=== 数值变量相关性分析 ===")
if not numeric_df.empty:
# 计算皮尔逊相关系数矩阵(范围从-1到1,分别表示强负相关、无相关、强正相关)
corr_matrix = numeric_df.corr().round(2)
print("相关系数矩阵:")
print(corr_matrix)
# 第二步:生成热力图进行可视化呈现
plt.figure(figsize=(10, 8))
im = plt.imshow(corr_matrix, cmap='RdBu_r', vmin=-1, vmax=1) # 使用红蓝配色方案
plt.colorbar(im, label='相关系数')
# 设置坐标轴显示变量名称,并旋转避免重叠
plt.xticks(range(len(corr_matrix.columns)), corr_matrix.columns, rotation=45, ha='right')
plt.yticks(range(len(corr_matrix.columns)), corr_matrix.columns)
# 在热图每个单元格内添加具体的相关系数数值
# 相关性热图绘制逻辑优化
plt.tight_layout()
plt.savefig('correlation_heatmap.png', dpi=300, bbox_inches='tight')
plt.show()
print("相关性热图已保存为 'correlation_heatmap.png'")
else:
print("无可用的数值型变量进行相关性分析")
[此处为图片1]
# 相关系数解读说明
- 系数接近 1:表示强正相关关系。例如,教育年限越长,获得高收入(>50K)的概率越高。
- 系数接近 -1:表示强负相关关系。例如,随着年龄增长,每周工作时长可能呈现下降趋势。
- 系数接近 0:表明两个变量之间缺乏明显的线性关联。例如,年龄与种族之间通常不存在显著的相关性。
[此处为图片2]
# 数据分析总结与成果导出
## 核心结论生成
print("=" * 60)
print(" ???????????????????美国社区调查数据分析总结报告")
print("=" * 60)
# 关键指标计算
total_samples = len(df_clean)
high_income_rate = (df_clean['income'] == '>50K').mean() * 100 if 'income' in df_clean.columns else 'N/A'
avg_age = df_clean['age'].mean().round(1) if 'age' in df_clean.columns else 'N/A'
avg_work_hours = df_clean['hours_per_week'].mean().round(1) if 'hours_per_week' in df_clean.columns else 'N/A'
male_avg_hours = df_clean[df_clean['sex'] == 'Male']['hours_per_week'].mean().round(1) if 'sex' in df_clean.columns else 'N/A'
female_avg_hours = df_clean[df_clean['sex'] == 'Female']['hours_per_week'].mean().round(1) if 'sex' in df_clean.columns else 'N/A'
# 输出综合摘要信息
summary = f"""
【数据基本信息】
? 清洗后样本总数:{total_samples:,} 条(原始:{len(df):,} 条)
? 分析时间:{pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}
? 核心字段数量:{len(df_clean.columns)} 个
【主要发现】
1. 收入结构:高收入群体(>50K)占比为 {high_income_rate:.1f}%,整体仍以中低收入人群为主
2. 年龄分布:平均年龄为 {avg_age} 岁,主体集中在20至50岁的劳动适龄阶段
3. 工作强度:周均工作时长为 {avg_work_hours} 小时;男性平均 {male_avg_hours} 小时,女性平均 {female_avg_hours} 小时
4. 教育作用:高学历者(如硕士、博士)更倾向于进入高收入阶层,教育水平对收入影响显著
5. 变量关联:教育年限与高收入概率呈正向关联,而年龄与工作时长之间未见明显线性关系
【实践建议】
? 职业发展路径:加强教育投入可有效提升个人收入潜力
? 组织管理策略:性别间工时差异值得关注,建议在人力资源配置中考虑公平与效率平衡
"""
print(summary)
print("=" * 60)
# 清洗后数据持久化存储
df_clean.to_csv('cleaned_census_data.csv', index=False, encoding='utf-8-sig')
print("? 清洗后的数据已保存为:cleaned_census_data.csv")
核心知识点总结(入门必掌握)
经过本次完整的数据分析实践,你已经系统掌握了数据分析的基本流程以及Pandas中的关键操作技能。以下是本次所涉及的核心内容概览:
| 技能模块 | 核心操作 | 应用场景 |
|---|---|---|
| 数据加载 | pd.read_csv()、远程URL加载 | 读取本地或网络上的数据文件 |
| 数据探索 | head()、info()、describe() | 快速查看数据结构与基本统计信息 |
| 数据清洗 | dropna()、drop_duplicates()、fillna() | 清理缺失值、重复记录并填充空缺数据 |
| 描述性统计 | mean()、median()、std() | 分析数值型变量的集中趋势与离散程度 |
| 分组聚合 | groupby()、agg()、apply() | 对不同类别进行对比分析和自定义计算 |
| 数据可视化 | 直方图、条形图、箱线图、热图 | 以图形方式直观呈现数据分布与规律 |
| 相关性分析 | corr()、热图可视化 | 挖掘变量之间的关联关系 |
| 结果导出 | to_csv()、savefig() | 保存处理后的数据及生成的图表 |
后续学习建议
- 动手实践修改代码:尝试更换其他数据集,例如泰坦尼克号生存数据、电商销售记录等,复用当前分析流程以巩固理解。
- 深入学习进阶功能:掌握Pandas中更强大的工具,如数据透视表(pivot_table())、条件筛选(query())以及时间序列处理方法。
- 实战能力提升:练习识别并处理异常值(如工作时长超过100小时的数据点),开展特征工程(例如将年龄细分为多个区间)以增强模型表现力。
[此处为图片1]
通过此次项目实战,你在数据分析道路上已迈出坚实的第一步。需要牢记的是,数据分析的本质并非编写代码本身,而是培养“从数据中发现问题、并通过分析解决问题”的思维方式。唯有持续练习、勤于思考,才能真正掌握这项核心能力。
[此处为图片2]
print("? 可视化图表已保存为:census_analysis_charts.png、correlation_heatmap.png")


雷达卡


京公网安备 11010802022788号







