TMDB 5000电影数据集:3步数据清洗实战,异常值处理与字段筛选详解
TMDB 5000电影数据集:3步数据清洗实战,异常值处理与字段筛选详解
电影数据分析的第一步往往不是建模或可视化,而是处理那些令人头疼的原始数据。当打开TMDB数据集时,你会发现预算为0的"大片"、时长仅1分钟的"电影",以及大量缺失的宣传语——这些数据质量问题会直接影响后续分析的可靠性。本文将带你用Pandas完成一次专业级的数据清洗,从4803条原始记录中提炼出3229条高质量数据。
1. 数据质量诊断:发现隐藏的问题
在动手清洗之前,我们需要像医生检查病人一样对数据集进行全面"体检"。使用Pandas的info()和describe()方法可以快速发现表面问题,但真正的挑战在于识别那些不易察觉的数据异常。
import pandas as pd # 加载数据集 movies = pd.read_csv('tmdb_5000_movies.csv') # 基础信息检查 print(movies.info()) # 数值型字段统计 print(movies[['budget', 'revenue', 'runtime']].describe())典型的数据质量问题通常表现为:
- 缺失值陷阱:
homepage字段缺失率高达82.4%,tagline缺失率也有82.3% - 异常值警报:
budget和revenue的最小值为0(占全部记录的32.7%) - 时间错乱:
release_date有少量缺失,且存在历史日期错误 - 字段冗余:如
id与imdb_id存在重复标识
更隐蔽的问题还包括JSON格式的嵌套字段(如genres和production_companies),这些字段需要特殊处理才能用于分析。通过初步检查,我们确定需要重点处理以下字段:
| 字段名 | 问题类型 | 问题严重程度 | 处理优先级 |
|---|---|---|---|
| budget | 零值异常 | 高 (31.8%) | 1 |
| revenue | 零值异常 | 高 (32.1%) | 1 |
| runtime | 零值/异常 | 中 (1.2%) | 2 |
| homepage | 缺失值 | 低 (分析无关) | 3 |
| tagline | 缺失值 | 低 (分析无关) | 3 |
2. 三阶清洗法:结构化处理流程
专业的数据清洗应该遵循分阶段、可回溯的原则。我们采用"过滤-修复-验证"的三阶清洗法,确保每个处理步骤都有明确的目的和可衡量的效果。
2.1 第一阶段:字段筛选与缺失处理
首先删除与分析目标无关的字段,然后处理缺失值:
# 删除非必要列 cols_to_drop = ['homepage', 'tagline', 'keywords', 'overview', 'imdb_id', 'poster_path'] movies_clean = movies.drop(cols_to_drop, axis=1) # 处理release_date缺失 movies_clean = movies_clean[movies_clean['release_date'].notna()] # 处理runtime缺失 - 用中位数填充 runtime_median = movies_clean['runtime'].median() movies_clean['runtime'] = movies_clean['runtime'].fillna(runtime_median)对于JSON格式的嵌套字段,我们进行扁平化处理:
# 解析genres字段示例 import json def parse_json_column(df, column): df[column] = df[column].apply( lambda x: ', '.join([i['name'] for i in json.loads(x)]) if pd.notna(x) else '' ) return df movies_clean = parse_json_column(movies_clean, 'genres') movies_clean = parse_json_column(movies_clean, 'production_companies')2.2 第二阶段:异常值处理策略
针对不同类型的异常值,我们采用差异化的处理方案:
预算/收入零值问题:
# 创建布尔掩码识别有效财务数据 financial_valid = (movies_clean['budget'] > 0) & (movies_clean['revenue'] > 0) movies_financial = movies_clean[financial_valid].copy() # 计算投入产出比 movies_financial['ROI'] = ( (movies_financial['revenue'] - movies_financial['budget']) / movies_financial['budget'] )电影时长异常处理:
# 过滤无效时长(小于45分钟或大于240分钟) time_filter = (movies_clean['runtime'] >= 45) & (movies_clean['runtime'] <= 240) movies_time = movies_clean[time_filter].copy() # 分箱处理 bins = [0, 60, 90, 120, 180, 240] labels = ['短片', '标准', '常规', '长篇', '超长'] movies_time['runtime_category'] = pd.cut( movies_time['runtime'], bins=bins, labels=labels )2.3 第三阶段:数据一致性验证
清洗完成后,我们需要验证数据质量:
# 验证财务数据 print(f"原始记录数: {len(movies)}") print(f"有效财务记录: {len(movies_financial)}") print(f"财务数据保留率: {len(movies_financial)/len(movies):.1%}") # 检查字段完整性 print("\n字段完整性检查:") print(movies_financial.isnull().sum()) # 验证异常值处理 print("\n时长分布验证:") print(movies_time['runtime_category'].value_counts())验证结果应该显示:
- 财务有效记录约3229条(保留率67.2%)
- 无关键字段缺失
- 时长分布符合电影行业常识
3. 高级清洗技巧与实战案例
对于复杂的数据质量问题,我们需要更精细的处理方法。
3.1 时间序列数据处理
处理时间字段时需要考虑格式统一和有效性:
# 统一日期格式 movies_clean['release_date'] = pd.to_datetime( movies_clean['release_date'], errors='coerce' ) # 提取时间特征 movies_clean['release_year'] = movies_clean['release_date'].dt.year movies_clean['release_month'] = movies_clean['release_date'].dt.month # 过滤不合理年份(早于1888年或晚于当前年份) current_year = pd.Timestamp.now().year year_filter = (movies_clean['release_year'] >= 1888) & ( movies_clean['release_year'] <= current_year ) movies_time_clean = movies_clean[year_filter].copy()3.2 文本字段标准化
对于文本类字段,需要进行标准化处理:
# 统一语言代码 movies_clean['original_language'] = movies_clean['original_language'].str.upper() # 处理标题特殊字符 movies_clean['clean_title'] = ( movies_clean['original_title'] .str.replace(r'[^\w\s]', '', regex=True) .str.strip() ) # 生成文本长度特征 movies_clean['title_length'] = movies_clean['clean_title'].str.len()3.3 关系型数据验证
检查数据间的逻辑关系可以捕获隐藏问题:
# 验证预算与收入关系 illogical_finance = movies_financial['budget'] > movies_financial['revenue'] print(f"异常财务记录: {illogical_finance.sum()}") # 验证评分与投票数关系 vote_filter = movies_clean['vote_count'] < 10 high_rating = movies_clean['vote_average'] >= 8 suspicious_ratings = vote_filter & high_rating print(f"可疑高评分电影: {suspicious_ratings.sum()}")4. 清洗结果与应用建议
经过系统清洗后,我们得到三个净化后的数据集:
财务分析专用集(3229条)
- 包含有效预算和收入数据
- 已计算ROI等衍生指标
时长分析专用集(4621条)
- 合理的电影时长范围(45-240分钟)
- 添加时长分类标签
时间序列分析集(4765条)
- 有效的时间范围(1888-当前年份)
- 提取年月等时间特征
针对不同分析场景,建议:
- 商业价值分析:使用财务分析集,重点关注ROI>1的电影
- 观众偏好研究:结合清洗后的评分和流行度数据
- 时间趋势分析:使用时间序列集,按年度/月份聚合
提示:始终保留原始数据和清洗脚本的对应版本,方便回溯和复现清洗过程
清洗后的数据可以支持更可靠的分析结论。例如,我们发现预算与收入并非简单线性关系——中等预算(2000-5000万美元)的电影往往有最佳ROI表现,而超高预算电影的投资回报率反而下降。