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

Posted

技术标签:

【中文标题】通过 Pandas 中的函数替换 NaN 时索引超出范围【英文标题】:Index out of bounds when replacing NaNs through a function in Pandas 【发布时间】:2017-05-20 16:41:31 【问题描述】:

我创建了一个函数,该函数将 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

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

【问题讨论】:

【参考方案1】:

我会将DataFrame.fillna() 方法与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

【讨论】:

【参考方案2】:

您得到“索引超出范围”的原因是因为您在分配值 df.mean()[i]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)

【讨论】:

我按照您的建议更改了函数中的代码,但仍然出现错误:IndexError: single positional indexer is out-of-bounds 我用示例 df 运行了那个确切的代码,它运行了。我得到了SettingWithCopyWarning,但它运行了。 是的,我明白这一点。事实上,正如我在帖子中提到的,甚至在测试数据帧中的校正运行之前,原始函数也是如此。但是,它在目标数据帧上失败了,可以在这里找到:ndownloader.figshare.com/files/2292172.. 你能解释一下吗?

以上是关于通过 Pandas 中的函数替换 NaN 时索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章

pandas使用replace函数将所有的无穷大值np.inf替换为缺失值np.nan使用pandas的fillna函数用经验固定值填充缺失值np.nan

Pandas 替换 NaN 值

用 pandas 中的 empty_rows 替换 pandas 数据框中的 NaN [重复]

pandas:用列中的最后一个非 NaN 值替换 NaN [重复]

Pandas - 用特定组的平均值替换列中的 NaN

重新索引系列返回 Pandas 中的 NaN