开发者

Python使用Pandas处理缺失值的技巧分享

目录
  • 一、缺失值的三种形态
  • 二、缺失值检测四步法
    • 1. 快速概览缺失情况
    • 2. 可视化缺失分布
    • 3. 识别隐性缺失
    • 4. 结构缺失检测
  • 三、缺失值处理实战方案
    • 方案1:直接删除(适用于缺失率<30%的列)
    • 方案2:填充固定值(适用于分类数据)
    • 方案3:统计量填充(适用于数值数据)
    • 方案4:模型预测填充(适用于关键字段)
    • 方案5:插值法(适用于有序数据)
  • 四、缺失值处理进阶技巧
    • 1. 分组填充(不同类别不同策略)
    • 2. 多重填充策略组合
    • 3. 缺失值标记法(保留信息)
  • 五、处理后的数据验证
    • 常见问题Q&A
      • 结语

        一、缺失值的三种形态

        爬虫数据中的缺失值通常以三种形式存在:

        • 显性缺失:直接显示为NoneNaN(Not a Number)
        • 隐性缺失:用特殊值代替(如"-"、"N/A"、"0")
        • 结构缺失:整行/整列数据缺失(如jsON解析失败导致的空字典)
        import pandas as pd
        import numpy as np
         
        # 模拟爬虫数据
        data = {
            '商品名称': ['iPhone13', '华为Mate50', None, '小米13', 'N/A'],
            '价格': [5999, 4999, np.nan, 3999, '-'],
            '销量': [1200, 800, 0, 1500, None],
            '库存': ['有货', '缺货', '有货', '有货', '']
        }
        df = pd.DataFrame(data)

        二、缺失值检测四步法

        1. 快速概览缺失情况

        # 查看每列缺失值数量
        print(df.isnull().sum())
         
        # 查看缺失值比例
        print(df.isnull().mean().round(2))

        输出结果会显示每列有多少缺失值及其占比,帮助判断哪些字段需要重点处理。

        2. 可视化缺失分布

        import missingno as msno
         
        msno.matrix(df.sample(5))  # 随机展示5行数据的缺失矩阵
        msno.bar(df)  # 柱状图展示各列缺失比例

        3. 识别隐性缺失

        # 自定义隐性缺失值列表
        hidden_missing = ['-', 'N/A', '无', '未知', '']
         
        # 检测包含隐性缺失的列
        for col in df.columns:
            if df[col].dtype in ['object', 'string']:
                missing_count = df[col].isin(hidden_missing).sum()
                if missing_count > 0:
                    print(f"{col}列发现{missing_count}个隐性缺失值")

        4. 结构缺失检测

        # 检查是否有整行为空的情况
        print("整行为空的记录数:", df.isnull().all(axis=1).sum())
         
        # 检查特定列组合缺失模式
        print(df[['价格', '销量']].isnull().sum())

        三、缺失值处理实战方案

        方案1:直接删除(适用于缺失率<30%的列)

        # 删除包含缺失值的行(谨慎使用)
        df_drop_rows = df.dropna()
         
        # 删除缺失值超过50%的列
        threshold = len(df) * 0.5
        df_drop_cols = df.dropna(thresh=threshold, axis=1)
         
        # 指定列删除(当价格缺失时删除整行)
        df_drop_specific = df.dropna(subset=['价格'])

        方案2:填充固定值(适用于分类数据)

        # 用"未知"填充商品名称缺失
        df['商品名称'] = df['商品名称'].fillna('未知')
         
        # 用0填充销量缺失(需确认业务逻辑)
        df['销量'] = df['销量'].fillna(0)
         
        # 批量处理文本列的隐性缺失
        text_cols = ['商品名称', '库存']
        for col in text_cols:
            df[col] = df[col].replace(hidden_missing, '未知')

        方案3:统计量填充(适用于数值数据)

        # 用中位数填充价格(抗异常值干扰)
        pythonmedian_price = df['价格'].median()
        df['价格'] = df['价格'].replace('-', np.nan).fillna(median_price)
         
        # 用均值填充销量(需数据分布均匀)
        mean_sales = df['销量'].mean()
        df['销量'] = df['销量'].fillna(mean_sales)
         
        # 前向填充(时间序列数据适用)
        df['价格'] = df['价格'].fillna(method='ffill')

        方案4:模型预测填充(适用于关键字段)

        from sklearn.ensemble import RandomForestRegressor
         
        # 准备数据(示例:用其他特征预测价格)
        known = df[df['价格'].notna()]
        unknown = df[df['价格'].isna()]
         
        X_known = known[['销量', '库存']]
        y_known = known['价格']
        X_unknown = unknown[['销量', '库存']]
         
        # 训练模型并预测
        model = RandomForestRegressor(n_estimators=100)
        model.fit(X_known, y_known)
        predicted_prices = model.predict(X_unknown)
         
        # 填充缺失值
        df.loc[df['价格'].isna(), '价格'] = predicted_prices

        方案5:插值法(适用于有序数据)

        # 创建带时间索引的示例数据
        dates = pd.date_range('2023-01-01', periods=5)
        temp_data = {'温度': [22, np.nan, 25, np.nan, 28]}
        temp_df = pd.DataFrame(temp_data, index=dates)
         
        # 线性插值
        temp_df['温度'] = temp_df['温度'].interpolate()
         
        # 时间加权插值(更平滑)
        temp_df['温度'] = temp_df['温度'].interpolate(method='time')

        四、缺失值处理进阶技巧

        php

        1. 分组填充(不同类别不同策略)

        # 按库存状态分组填充价格
        def fill_price(group):
            if group.name == '有货':
                return group.fillna(group.median())
            else:
                return group.fillna(0)  # 缺货商品可能标0价
         
        df['价格'] = df.groupby('库存')['价格'].apply(fill_price)

        2. 多重填充策略组合

        # 先填充隐性缺失,再填充显性缺失
        for col in ['价格', '销量']:
            # 处理隐性缺失
            if df[col].dtype == 'object':
                df[col] = df[col].replace('-', np.nan)
            
            # 根据缺失率选择填充方式
            missing_rate = df[col].isna().mean()
            if missing_rate < 0.1:
                df[col] = df[col].fillna(df[col].median())
            elif missing_rate < 0.3:
                df[col] = df[col].fillna(df[col].mean())
            ehttp://www.devze.comlse:
                df[col] = df[col].fillna(-1)  # 标记特殊值

        3. 缺失值标记法(保留信息)

        # 创建缺失标记列
        for chttp://www.devze.comol in ['价格', '销量']:
            df[f'{col}_is_missing'] = df[col].isna().astype(int)
         
        # 然后填充缺失值
        df['价格'] = df['价格'].fillna(df['价格'].median())

        五、处理后的数据验证

        # 验证缺失值是否处理完成
        print("剩余缺失值数量:\n", df.isnull().sum())
         
        # 检查填充值是否合理
        print("价格描述统计:\n", df['价格'].describe())
        print("销量分布:\n", df['销量'].value_counts())
         
        # 可视化验证
        import matplotlib.pyplot as plt
         
        plt.figure(figsize=(10, 4))
        plt.subplot(1, 2, 1)
        df['价格'].plot(kind='hist', title='价格分布')
        plt.subplot(1, 2, 2)
        df['销量'].plot(kind='hist', title='销量分布')
        plt.tight_layout()
        plt.show()

        常见问题Q&AYtmYSvzWkS

        Q1:被网站封IP怎么办?

        A:立即启用备用代理池,建议使用住宅代理(如站大爷IP代理),配合每请求更换IP策略。更稳妥的方式是使用爬虫框架(如Scrapy)的中间件实现自动切换。

        Q2:如何选择填充值?

        A:根据数据类型和业务逻辑决定:

        • 数值型:中位数(抗异常值)> 均值(数据分布均匀时)> 固定值
        • 类别型:众数 > "未知" > 新类别
        • 时间序列:插值法 > 前向填充 > 固定值

        Q3:缺失值处理会影响数据分析结果吗?

        A:会。不当处理可能导致:

        • 均值/方差计算偏差
        • 模型过拟合(如用均值填充造成虚假集中趋势)
        • 分类模型准确率下降(错误填充改变数据分布)

        Q4:什么时候应该删除缺失值?

        A:满足以下条件时考虑删除:

        • 缺失率超过70%的列
        • 关键字段缺失的记录(如订单ID缺失)
        • 缺失机制完全随机(MCAR)且样本量充足

        Q5:如何自动化缺失值处理流程?

        A:可创建处理管道:

        from sklearn.pipeline import Pipeline
        from sklearn.impute import SimpleImputer
         
        def preprocess_data(df):
            numeric_features = ['价格', '销量']
            categorical_features = ['商品名称', '库存']
            
            numeric_transformer = Pipeline(steps=[
                ('imputer', SimpleImputer(strategy='median'))
            ])
            
            categorical_transformer = Pipeline(steps=[
                ('imputer', SimpleImputer(strategy='constant', fill_value='未知'))
            ])
            
            # 实际应用中可使用ColumnTransformer组合处理
            # 此处仅为示例结构
            return processed_df

        结语

        处理缺失值就像修理一辆二手车:不是简单更换损坏零件,而是要理解每个缺失背后的原因。有时缺失本身就包含信息(如用户未填写收入可能暗示低收入群体),过度填充反而会丢失价值。建议每次处理后都保存处理日志,记录缺失率、填充策略和验证结果,为后续分析提供可追溯的依据。

        以上就是python使用Pandas处理缺失值的技巧分享的详细内容,更多关于Python Pandas处理缺失值的资料请关注编程客栈(www.devze.com)其它相关文章!

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜