为什么在数据帧上具有中位数的 fillna 仍然在 pandas 中留下 Na/NaN?

Why does fillna with median on dataframe still leaves Na/NaN in pandas?

我在此处看到了 and this 话题,但还有其他问题。

我有一个非常大的 pandas DataFrame,有很多 Na/NaN 值。我想用该特征的中值替换它们。

所以,我首先制作一个 table 显示每个特征的 Na 值,按大多数 Na 值排序,然后使用 fillna(),然后再次显示 table。理想情况下,第二次 table 应该全为 0,因为所有 Na 都已被填充。

nullCount = pd.DataFrame(TT_df.isnull().sum(),columns=["nullcount"]).sort_values(by="nullcount",ascending=False)
display(nullCount.head(10))

TT_df = TT_df.fillna(TT_df.median())

nullCount = pd.DataFrame(TT_df.isnull().sum(),columns=["nullcount"]).sort_values(by="nullcount",ascending=False)
display(nullCount.head(10))

但是,我得到了这两个 tables:

null count tables, before and after

如果我看一下 DataFrame,您可以在其中看到 NaN:

display(TT_df[nullCount.index.tolist()[0:5]].head(50))

NaN examples

似乎 fillna() 的一个常见问题是它 returns 一个副本,除非你使用 inplace=True (就像在上面的链接线程中一样),但我 not 这样做:我正在覆盖 TT_df,除非我误解了什么。您可以看到 LotFrontage 功能实际上确实从第二个 table 中消失了,这意味着 fillna() did 为它工作。那为什么它对其他人不起作用?

我怀疑是罪魁祸首,虽然我不知道为什么,但对于这些特征,Na 实际上并不意味着 Na:如果我查看数据描述文件,它说:

GarageFinish: Interior finish of the garage

   Fin    Finished
   RFn    Rough Finished  
   Unf    Unfinished
   NA No Garage

好的,没关系。但感觉那些 NA 值应该对 isnull() 和 fillna() 都算作 Na,或者两者都不算。为什么它似乎被 isnull() 计数而不是 fillna()?

这一行有问题:

TT_df = TT_df.fillna(TT_df.median())

您的数据框包含字符串,您正在尝试计算字符串的中位数。这行不通。

这是一个最小的例子:

import pandas as pd, numpy as np

df = pd.DataFrame({'A': ['A', 'B', np.nan, 'B']})

df = df.fillna(df.median())

print(df)

     A
0    A
1    B
2  NaN
3    B

您应该做的是 fillna 仅对数字列设置中位数:

for col in df.select_dtypes(include=np.number):
    df[col] = df[col].fillna(df[col].median())