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 os def load_hurun_data(file_path: str) - pd.DataFrame: 读取胡润富豪榜原始数据 :param file_path: 文件路径 :return: 清洗前的DataFrame if not os.path.exists(file_path): raise FileNotFoundError(f文件不存在: {file_path}) # 关键:处理编码问题,中文数据常见utf-8-sig df = 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 np def clean_wealth_value(val): 将各种格式的财富值统一转换为亿元为单位的浮点数 :param val: 原始字符串或数字 :return: 亿元为单位的float,无效返回np.nan if 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.nan number_str = match.group(1) unit = match.group(2) # 去掉千分位逗号 number = float(number_str.replace(',', '')) # 根据单位转换 if unit == '亿元': return number elif unit == '万元': return number / 10000.0 elif unit == '元': return number / 100000000.0 else: # 默认假设是亿元(胡润榜单通常如此) return number def 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. 处理缺失值:排名不能为空,财富值缺失的标记为0 df = 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 pd def 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.0 assert clean_wealth_value(10,000万元) == 1.0 assert clean_wealth_value(100000000元) == 1.0 assert clean_wealth_value(95.5亿) == 95.5 assert clean_wealth_value(abc) == np.nan print(所有测试通过!) 在 main.py 里加一行 test_clean_wealth_value(),每次改代码都跑一下,确保没改坏原有逻辑。这种习惯,GitHub 开源仓库里的项目都有,不是形式主义,是保命符。 优化扩展:从能用到处用 基础功能跑通后,别停。想想这个数据还能干啥? 1. 行业分布分析 # src/visualizer.py import matplotlib.pyplot as plt import pandas as pd def 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'] * 100 top_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年的,也能处理银行流水、销售报表、用户日志。方法是一样的,只是数据字段不同。 现在打开你的终端,建个目录,把上面的代码敲进去,跑一遍。跑不通的地方,就是你要深入学习的点。 还有什么不懂的?评论区留言挨个回