通过 Pandas 中的函数替换 NaN 时索引超出范围

Index out of bounds when replacing NaNs through a function in Pandas

我创建了一个函数,用相应列的方法替换 Pandas 数据框中的 NaN。我用一个小的数据框测试了这个函数,它起作用了。当我将它应用于更大的数据框(30,000 行,9 列)时,我收到错误消息:IndexError: index out of bounds

函数如下:

# The 'update' function will replace all the NaNs in a dataframe with the mean of the respective columns

def update(df):   # the function takes one argument, the dataframe that will be updated
      ncol = df.shape[1]  # number of columns in the dataframe
      for i in range(0 , ncol):  # loops over all the columns
             df.iloc[:,i][df.isnull().iloc[:, i]]=df.mean()[i]  # subsets the df using the isnull() method, extracting the positions
                                                        # in each column where the 
      return(df)

我用来测试功能的小数据框如下:

     0   1   2  3
0   NaN NaN  3  4
1   NaN NaN  7  8
2   9.0 10.0 11 12

你能解释一下这个错误吗?我们将不胜感激您的建议。

我会使用DataFrame.fillna() method in conjunction with DataFrame.mean()方法:

In [130]: df.fillna(df.mean())
Out[130]:
     0     1   2   3
0  9.0  10.0   3   4
1  9.0  10.0   7   8
2  9.0  10.0  11  12

平均值:

In [138]: df.mean()
Out[138]:
0     9.0
1    10.0
2     7.0
3     8.0
dtype: float64

你得到 "index out of bounds" 的原因是因为当 i 是应该是序数位置的迭代时,你正在分配值 df.mean()[i]df.mean() 是一个 Series,其索引是 df 的列。 df.mean()[something] 表示 something 最好是列名。但它们不是,这就是为什么您会收到错误消息的原因。

您的代码...已修复

def update(df):   # the function takes one argument, the dataframe that will be updated
      ncol = df.shape[1]  # number of columns in the dataframe
      for i in range(0 , ncol):  # loops over all the columns
             df.iloc[:,i][df.isnull().iloc[:, i]]=df.mean().iloc[i]  # subsets the df using the isnull() method, extracting the positions
                                                        # in each column where the 
      return(df)

此外,您的函数正在直接更改 df。你可能要小心。我不确定那是你想要的。


说了这么多。我推荐另一种方法

def update(df):
    return df.where(df.notnull(), df.mean(), axis=1)

您可以使用任意数量的方法来用均值填充缺失值。我建议使用@MaxU 的答案。

df.where
当第一个参数为 True 时采用 df 否则第二个参数为

df.where(df.notnull(), df.mean(), axis=1)

df.combine_first用尴尬pandas广播

df.combine_first(pd.DataFrame([df.mean()], df.index))

np.where

pd.DataFrame(
    np.where(
        df.notnull(), df.values,
        np.nanmean(df.values, 0, keepdims=1)),
    df.index, df.columns)