3步搞定2014胡润中国富豪榜数据清洗,保姆级教程
3步搞定2014胡润中国富豪榜数据清洗,保姆级教程
看了一堆教程还是不会写项目?别慌,这篇保姆级教程带你从零到一。
很多人卡在“数据怎么处理”这一步,觉得财经数据高大上,其实拆开看就是几行代码的事。今天我们就拿2014胡润中国富豪榜当练手项目,手把手教你把原始数据变成能直接用的结构化信息。
项目目标:把榜单变成数据库
咱们先明确要干啥。原始榜单通常是Excel或者PDF,里面混杂着排名、姓名、财富值、行业、籍贯这些字段,但格式不统一,有的带空格,有的单位是“亿元”,有的是“万元”。
我们的目标是:读取原始数据文件
清洗脏数据(去空格、统一单位、处理缺失值)
转换成标准CSV格式
做个简单的可视化,看看前10名都干啥的做完这个,你就拥有了一个可复用的数据清洗流程,以后换2024年的榜单,改个文件名就行。
目录结构:保持工程化习惯
别以为写几个脚本就完了,真正的工程化从目录结构开始。哪怕是个小项目,也要有模有样。
hurun_2014_project/
├── data/
│ └── hurun_2014_raw.csv # 原始数据
├── src/
│ ├── __init__.py
│ ├── data_loader.py # 数据读取模块
│ ├── data_cleaner.py # 数据清洗模块
│ └── visualizer.py # 可视化模块
├── output/
│ └── hurun_2014_clean.csv # 清洗后的数据
├── requirements.txt # 依赖管理
└── main.py # 主入口这种结构看着简单,但以后扩展功能时,你不用翻代码找逻辑。data_loader.py 只负责读,data_cleaner.py 只负责洗,visualizer.py 只负责画,各司其职。
我见过太多人把几千行代码堆在一个 main.py 里,最后自己都不敢改。这种目录结构,GitHub 开源仓库里到处都是,照着抄就行。
核心代码实现:逐行讲透
1. 环境准备
先装依赖,别用 pip install *,那样太乱。requirements.txt 里写清楚版本:
pandas==2.0.3
matplotlib==3.7.2
numpy==1.24.3用 conda 或者 venv 建个虚拟环境,跑 pip install -r requirements.txt。这一步别省,环境不一致是新手最大的坑。
2. 数据读取:别直接用 pd.read_csv
很多人一上来就 pd.read_csv('raw.csv'),结果发现有的行是空的,有的列名带空格。我们写个稳健的读取函数:
# src/data_loader.py
import pandas as pd
import osdef load_hurun_data(file_path: str) - pd.DataFrame:读取胡润富豪榜原始数据:param file_path: 文件路径:return: 清洗前的DataFrameif not os.path.exists(file_path):raise FileNotFoundError(f文件不存在: {file_path})# 关键:处理编码问题,中文数据常见utf-8-sigdf = pd.read_csv(file_path, encoding='utf-8-sig', skipinitialspace=True)# 去除列名中的空格df.columns = [col.strip() for col in df.columns]print(f成功读取数据: {len(df)} 条记录)return df注意 encoding='utf-8-sig',这是Windows下Excel导出的CSV常见编码,不带这个参数,中文全是乱码。skipinitialspace=True 则是为了去掉字段前的空格,比如 姓名 变成 姓名。
3. 数据清洗:最核心的部分
这是最容易出错的地方。2014年的榜单里,财富值有的写“100亿”,有的写“100,000,000,000元”,还有的是“95.5亿”。我们统一成“亿元”为单位的浮点数。
# src/data_cleaner.py
import pandas as pd
import re
import numpy as npdef clean_wealth_value(val):将各种格式的财富值统一转换为亿元为单位的浮点数:param val: 原始字符串或数字:return: 亿元为单位的float,无效返回np.nanif pd.isna(val):return np.nan# 转为字符串处理val_str = str(val).strip()# 去掉货币符号和空格val_str = val_str.replace('¥', '').replace('¥', '').replace(' ', '')# 匹配数字部分# 规则:数字(可选千分位逗号)(可选小数点)(可选单位)match = re.match(r'^(\d{1,3}(?:,\d{3})*(?:\.\d+)?|\d+(?:\.\d+)?)\s*(亿元|万元|元)?$', val_str)if not match:# 尝试简单数字解析try:return float(val_str.replace(',', ''))except ValueError:return np.nannumber_str = match.group(1)unit = match.group(2)# 去掉千分位逗号number = float(number_str.replace(',', ''))# 根据单位转换if unit == '亿元':return numberelif unit == '万元':return number / 10000.0elif unit == '元':return number / 100000000.0else:# 默认假设是亿元(胡润榜单通常如此)return numberdef clean_dataframe(df: pd.DataFrame) - pd.DataFrame:清洗整个DataFrame:param df: 原始DataFrame:return: 清洗后的DataFrame# 1. 去除姓名中的空格df['姓名'] = df['姓名'].str.strip()# 2. 转换财富值df['财富值_亿元'] = df['财富值'].apply(clean_wealth_value)# 3. 处理缺失值:排名不能为空,财富值缺失的标记为0df = df.dropna(subset=['排名'])df['财富值_亿元'] = df['财富值_亿元'].fillna(0)# 4. 类型转换:排名转为整数df['排名'] = df['排名'].astype(int)# 5. 去重:同一人可能出现多次(极端情况)df = df.drop_duplicates(subset=['姓名'], keep='first')print(f清洗后剩余: {len(df)} 条记录)return df这里用正则表达式匹配单位,是因为真实数据里,100亿、100 亿元、100亿元 都可能存在。apply 函数逐行处理,虽然慢点,但清晰易懂,对于几千行的数据完全够用。
4. 主程序串联
# main.py
from src.data_loader import load_hurun_data
from src.data_cleaner import clean_dataframe
from src.visualizer import plot_top10
import pandas as pddef main():# 1. 读取raw_df = load_hurun_data('data/hurun_2014_raw.csv')# 2. 清洗clean_df = clean_dataframe(raw_df)# 3. 保存clean_df.to_csv('output/hurun_2014_clean.csv', index=False, encoding='utf-8-sig')print(清洗后数据已保存至 output/hurun_2014_clean.csv)# 4. 可视化plot_top10(clean_df)if __name__ == '__main__':main()运行与测试:别只跑通就完事
跑完 python main.py,别急着看图表。先检查 output/hurun_2014_clean.csv:打开CSV,看财富值列,有没有出现 nan 或异常小的数字?如果有,说明清洗逻辑有漏洞。
检查排名是否连续,有没有跳号?胡润榜单排名是唯一的,如果有重复,去重逻辑可能没生效。
对比原始数据的前10名,看清洗后的结果是否一致。我建议在 data_cleaner.py 里加个测试函数:
def test_clean_wealth_value():测试财富值清洗函数assert clean_wealth_value(100亿元) == 100.0assert clean_wealth_value(10,000万元) == 1.0assert clean_wealth_value(100000000元) == 1.0assert clean_wealth_value(95.5亿) == 95.5assert clean_wealth_value(abc) == np.nanprint(所有测试通过!)在 main.py 里加一行 test_clean_wealth_value(),每次改代码都跑一下,确保没改坏原有逻辑。这种习惯,GitHub 开源仓库里的项目都有,不是形式主义,是保命符。
优化扩展:从能用到处用
基础功能跑通后,别停。想想这个数据还能干啥?
1. 行业分布分析
# src/visualizer.py
import matplotlib.pyplot as plt
import pandas as pddef plot_top10(df: pd.DataFrame):绘制前10名财富值柱状图top10 = df.nlargest(10, '财富值_亿元')plt.figure(figsize=(10, 6))plt.barh(top10['姓名'], top10['财富值_亿元'], color='steelblue')plt.xlabel('财富值(亿元)')plt.title('2014胡润中国富豪榜 Top 10')plt.gca().invert_yaxis() # 排名靠前的在上面plt.tight_layout()plt.savefig('output/top10.png', dpi=150)plt.show()def plot_industry_distribution(df: pd.DataFrame):绘制行业财富总额分布industry_sum = df.groupby('行业')['财富值_亿元'].sum().sort_values(ascending=False)plt.figure(figsize=(12, 6))plt.bar(industry_sum.index, industry_sum.values, color='coral')plt.xticks(rotation=45, ha='right')plt.xlabel('行业')plt.ylabel('财富总额(亿元)')plt.title('2014胡润富豪榜各行业财富分布')plt.tight_layout()plt.savefig('output/industry_dist.png', dpi=150)plt.show()2. 同比分析
如果你有2013年的数据,可以加个对比模块:
def compare_years(df_2014: pd.DataFrame, df_2013: pd.DataFrame):对比两年数据,找出财富增长最快的人merged = df_2014.merge(df_2013[['姓名', '财富值_亿元']], on='姓名', suffixes=('_2014', '_2013'))merged['增长额'] = merged['财富值_亿元_2014'] - merged['财富值_亿元_2013']merged['增长率'] = merged['增长额'] / merged['财富值_亿元_2013'] * 100top_growers = merged.nlargest(10, '增长额')return top_growers这种扩展,让你从一个“跑通代码的人”变成“能分析数据的人”。
3. 打包成CLI工具
用 click 或 argparse 把 main.py 包装成命令行工具:
python -m hurun_project --input data/2014.csv --output output/ --top 20这样以后处理其他年份,不用改代码,换个参数就行。GitHub 上很多工具都是这么做的,用户体验直接拉满。
小结:比代码更重要的事
这个项目代码量不大,但踩的坑不少。编码问题、单位不统一、缺失值处理、去重逻辑,这些都是真实数据里的常见问题。
记住几个关键点:永远别相信原始数据是干净的,读取时就要做防御性处理
模块分离,读取、清洗、可视化分开,方便调试和扩展
写测试,哪怕只是几个 assert,也能避免低级错误
版本控制,把这个项目推到 GitHub 上,记录每次修改编程不是背语法,是解决实际问题。你能把2014年的榜单处理干净,就能处理2024年的,也能处理银行流水、销售报表、用户日志。方法是一样的,只是数据字段不同。
现在打开你的终端,建个目录,把上面的代码敲进去,跑一遍。跑不通的地方,就是你要深入学习的点。
还有什么不懂的?评论区留言挨个回