【问题标题】:pandas DataFrame: replace nan values with average of columnspandas DataFrame:用列的平均值替换nan值
【发布时间】:2013-09-12 10:41:45
【问题描述】:

我有一个大部分填充实数的 pandas DataFrame,但其中也有一些 nan 值。

如何将nans 替换为它们所在列的平均值?

这个问题与这个问题非常相似:numpy array: replace nan values with average of columns,但不幸的是,那里给出的解决方案不适用于 pandas DataFrame。

【问题讨论】:

    标签: python pandas nan


    【解决方案1】:

    您可以简单地使用DataFrame.fillna 直接填写nan

    In [27]: df 
    Out[27]: 
              A         B         C
    0 -0.166919  0.979728 -0.632955
    1 -0.297953 -0.912674 -1.365463
    2 -0.120211 -0.540679 -0.680481
    3       NaN -2.027325  1.533582
    4       NaN       NaN  0.461821
    5 -0.788073       NaN       NaN
    6 -0.916080 -0.612343       NaN
    7 -0.887858  1.033826       NaN
    8  1.948430  1.025011 -2.982224
    9  0.019698 -0.795876 -0.046431
    
    In [28]: df.mean()
    Out[28]: 
    A   -0.151121
    B   -0.231291
    C   -0.530307
    dtype: float64
    
    In [29]: df.fillna(df.mean())
    Out[29]: 
              A         B         C
    0 -0.166919  0.979728 -0.632955
    1 -0.297953 -0.912674 -1.365463
    2 -0.120211 -0.540679 -0.680481
    3 -0.151121 -2.027325  1.533582
    4 -0.151121 -0.231291  0.461821
    5 -0.788073 -0.231291 -0.530307
    6 -0.916080 -0.612343 -0.530307
    7 -0.887858  1.033826 -0.530307
    8  1.948430  1.025011 -2.982224
    9  0.019698 -0.795876 -0.046431
    

    fillna 的文档字符串说 value 应该是标量或字典,但是,它似乎也可以与 Series 一起使用。如果你想传递一个字典,你可以使用df.mean().to_dict()

    【讨论】:

    • df.fillna(df.mean()) 将返回新的数据帧,因此您必须写 df=df.fillna(df.mean()) 来保留它。
    • 有什么想法,为什么我可能会得到错误的估算值?
    • 你也可以用df=df.fillna(df.mean())代替df.fillna(df.mean(), inplace=True)
    • 注意:如果您想将其用于机器学习/数据科学:从数据科学的角度来看,首先替换 NA 然后拆分为训练和测试是错误。 ..你必须先拆分成train和test,然后在train上用mean替换NA,然后应用这个有状态的预处理模型来测试,下面涉及sklearn的答案!
    • @amalik2205 因为否则您会将测试集中的信息泄漏到训练集中!想象一下:我们有 100 个数据行,我们考虑第 x 列。 x 的前 99 个条目是 NA。我们想将第 100 行拆分为测试集。假设第 100 行在 x 列中的值为 20。然后,您将 x 列中训练集中的所有条目替换为 20,该值 100% 来自测试集。因此,评估可能会欺骗您!
    【解决方案2】:

    试试:

    sub2['income'].fillna((sub2['income'].mean()), inplace=True)
    

    【讨论】:

    • 对于想知道 inplace = True 的人:如果为 True,则原始对象会通过此更改进行修改。如果为 False(默认),该函数不会修改原始对象,而是返回其修改后的副本,您必须将其分配给原始对象以替换它。
    【解决方案3】:
    In [16]: df = DataFrame(np.random.randn(10,3))
    
    In [17]: df.iloc[3:5,0] = np.nan
    
    In [18]: df.iloc[4:6,1] = np.nan
    
    In [19]: df.iloc[5:8,2] = np.nan
    
    In [20]: df
    Out[20]: 
              0         1         2
    0  1.148272  0.227366 -2.368136
    1 -0.820823  1.071471 -0.784713
    2  0.157913  0.602857  0.665034
    3       NaN -0.985188 -0.324136
    4       NaN       NaN  0.238512
    5  0.769657       NaN       NaN
    6  0.141951  0.326064       NaN
    7 -1.694475 -0.523440       NaN
    8  0.352556 -0.551487 -1.639298
    9 -2.067324 -0.492617 -1.675794
    
    In [22]: df.mean()
    Out[22]: 
    0   -0.251534
    1   -0.040622
    2   -0.841219
    dtype: float64
    

    应用每列的平均值并填充

    In [23]: df.apply(lambda x: x.fillna(x.mean()),axis=0)
    Out[23]: 
              0         1         2
    0  1.148272  0.227366 -2.368136
    1 -0.820823  1.071471 -0.784713
    2  0.157913  0.602857  0.665034
    3 -0.251534 -0.985188 -0.324136
    4 -0.251534 -0.040622  0.238512
    5  0.769657 -0.040622 -0.841219
    6  0.141951  0.326064 -0.841219
    7 -1.694475 -0.523440 -0.841219
    8  0.352556 -0.551487 -1.639298
    9 -2.067324 -0.492617 -1.675794
    

    【讨论】:

    • 我不知道为什么,但是 df.fillna(df.mean()) 没有工作,只有你的版本适用。 Python 3
    【解决方案4】:

    虽然下面的代码完成了这项工作,但它的性能受到了很大的影响,因为您处理的 DataFrame 的记录数为 100k 或更多:

    df.fillna(df.mean())
    

    根据我的经验,应该仅在需要的地方替换 NaN 值(无论是平均值还是中位数),而不是在整个 DataFrame 中应用 fillna()

    我有一个包含 20 个变量的 DataFrame,其中只有 4 个需要 NaN 值处理(替换)。我尝试了上面的代码(代码 1),以及它的稍微修改的版本(代码 2),我有选择地运行它。即仅适用于具有 NaN 值的变量

    #------------------------------------------------
    #----(Code 1) Treatment on overall DataFrame-----
    
    df.fillna(df.mean())
    
    #------------------------------------------------
    #----(Code 2) Selective Treatment----------------
    
    for i in df.columns[df.isnull().any(axis=0)]:     #---Applying Only on variables with NaN values
        df[i].fillna(df[i].mean(),inplace=True)
    
    #---df.isnull().any(axis=0) gives True/False flag (Boolean value series), 
    #---which when applied on df.columns[], helps identify variables with NaN values
    

    以下是我观察到的性能,因为我不断增加 DataFrame 中的 # 条记录

    数据帧约 10 万条记录

    • 代码 1:22.06 秒
    • 代码 2:0.03 秒

    数据帧约 20 万条记录

    • 代码 1:180.06 秒
    • 代码 2:0.06 秒

    拥有约 160 万条记录的 DataFrame

    • 代码 1:代码无休止地运行
    • 代码 2:0.40 秒

    拥有约 1300 万条记录的 DataFrame

    • 代码 1:--在看到 160 万条记录的性能后甚至没有尝试--
    • 代码 2:3.20 秒

    抱歉,回答很长!希望这会有所帮助!

    【讨论】:

    • 我有timed it以上所有方法,你的方法是最快的。谢谢大佬。
    【解决方案5】:
    # To read data from csv file
    Dataset = pd.read_csv('Data.csv')
    
    X = Dataset.iloc[:, :-1].values
    
    # To calculate mean use imputer class
    from sklearn.impute import SimpleImputer
    imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
    imputer = imputer.fit(X[:, 1:3])
    X[:, 1:3] = imputer.transform(X[:, 1:3])
    

    【讨论】:

    • 与更简单的替代方案相比,这一切有什么优势?
    • @Roshan Jha 解释逻辑总是更好的。在 R & Python 中有很多方法可以完成相同的任务。但是,如果您提出不同的建议,您可能需要指出这样做的一些好处
    【解决方案6】:

    如果您想用均值来估算缺失值,并且您想逐列进行,那么这只会用该列的平均值来估算。这可能更具可读性。

    sub2['income'] = sub2['income'].fillna((sub2['income'].mean()))
    

    【讨论】:

    • 请提供一些解释如何解决问题。
    【解决方案7】:

    直接用df.fillna(df.mean())把所有的空值都填上均值

    如果你想用该列的平均值填充空值,那么你可以使用这个

    假设x=df['Item_Weight'] 这里Item_Weight 是列名

    我们在这里赋值(用 x 的平均值填充 x 的空值到 x 中)

    df['Item_Weight'] = df['Item_Weight'].fillna((df['Item_Weight'].mean()))
    

    如果你想用一些字符串填充空值,那么使用

    这里Outlet_size是列名

    df.Outlet_Size = df.Outlet_Size.fillna('Missing')
    

    【讨论】:

      【解决方案8】:

      除上述之外的另一个选择是:

      df = df.groupby(df.columns, axis = 1).transform(lambda x: x.fillna(x.mean()))
      

      它不如以前的平均值响应优雅,但如果您希望用其他列函数替换空值,它可能会更短。

      【讨论】:

        【解决方案9】:

        Pandas:如何将 NaN (nan) 值替换为一列的平均值、中位数或其他统计数据

        假设您的 DataFrame 是 df,并且您有一个名为 nr_items 的列。这是:df['nr_items']

        如果您想替换 df['nr_items'] 列的NaN 值与列的平均值

        使用方法.fillna()

        mean_value=df['nr_items'].mean()
        df['nr_item_ave']=df['nr_items'].fillna(mean_value)

        我创建了一个名为nr_item_ave 的新df 列来存储新列,其中NaN 值替换为列的mean 值。

        使用mean 时应小心。如果您有异常值,更推荐使用median

        【讨论】:

          【解决方案10】:

          使用sklearn库预处理类

          from sklearn.impute import SimpleImputer
          missingvalues = SimpleImputer(missing_values = np.nan, strategy = 'mean', axis = 0)
          missingvalues = missingvalues.fit(x[:,1:3])
          x[:,1:3] = missingvalues.transform(x[:,1:3])
          

          注意:在最近的版本中参数missing_values的值从NaN更改为np.nan

          【讨论】:

            【解决方案11】:

            我使用这种方法通过列的平均值来填充缺失值。

            fill_mean = lambda col : col.fillna(col.mean())
            
            df = df.apply(fill_mean, axis = 0)
            

            【讨论】:

              【解决方案12】:

              您还可以使用value_counts 来获取最常见的值。这适用于不同的数据类型。

              df = df.apply(lambda x:x.fillna(x.value_counts().index[0]))
              

              Here 是 value_counts api 引用。

              【讨论】:

                猜你喜欢
                • 2016-01-08
                • 2013-04-01
                • 2018-11-14
                • 2020-01-16
                • 1970-01-01
                • 2019-03-21
                • 1970-01-01
                相关资源
                最近更新 更多