Series.replace无法使用类似字典的to_replace和非None值。

17 浏览
0 Comments

Series.replace无法使用类似字典的to_replace和非None值。

我的pandas DataFrame主要由实数填充,但也有一些nan值。

我该如何用它们所在列的平均值替换nan值?

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

0
0 Comments

Series.replace不能使用类字典的to_replace和非None值。问题的原因是Series.replace()方法在使用类字典的to_replace参数时,不支持传入一个字典,而是要求传入一个标量值或者一个Series。解决方法是将to_replace参数改为一个标量值或者Series,或者使用其他方法替代Series.replace()。

文章如下:

虽然下面的代码能够完成工作,但是性能会受到很大影响,特别是当处理包含10万条或更多记录的DataFrame时:

df.fillna(df.mean())

根据我的经验,应该只在必要的情况下替换NaN值(无论是用平均值还是中位数),而不是在整个DataFrame上应用fillna()。

我有一个包含20个变量的DataFrame,只有其中的4个变量需要处理NaN值(替换)。我尝试了上面的代码(代码1),以及稍微修改过的版本(代码2),只在有NaN值的变量上运行代码2。

#------------------------------------------------
#----(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中记录数量的增加而增加。

DataFrame中有约10万条记录:

- 代码1:22.06秒

- 代码2:0.03秒

DataFrame中有约20万条记录:

- 代码1:180.06秒

- 代码2:0.06秒

DataFrame中有约160万条记录:

- 代码1:代码一直在运行,没有结束

- 代码2:0.40秒

DataFrame中有约1300万条记录:

- 代码1:在看到160万条记录的性能后,没有尝试

- 代码2:3.20秒

对于回答如此之长表示歉意!希望能对你有所帮助!我已经对上述所有方法进行了计时,你的方法是最快的。谢谢!

快!!!!!!

0
0 Comments

在上述代码中,使用了DataFrame的fillna方法来填充缺失值。通过传入df.mean()作为参数,可以用该DataFrame的均值来填充缺失值。然而,对于Series的replace方法,在使用类似字典的to_replace和非None的value参数时是无法使用的。

解决方法是使用fillna方法时,可以将df.mean()转换为字典形式,即df.mean().to_dict()。这样就可以传入字典形式的参数,成功填充缺失值。

此外,需要注意的是,使用df.fillna(df.mean())会返回新的DataFrame,如果想保留更改,需要将其赋值给原来的DataFrame,即df=df.fillna(df.mean())。

如果想在原地修改DataFrame,也可以使用df.fillna(df.mean(), inplace=True)来实现。

需要注意的是,如果将该方法用于机器学习或数据科学,先替换缺失值再分割数据集是错误的。正确的做法是先将数据集分割为训练集和测试集,然后在训练集上计算均值并替换缺失值,最后将这个模型应用于测试集。这样可以避免将测试集的信息泄漏到训练集中。

有人可能会问,为什么不使用df.fillna(df.mean(1))来计算列平均值?实际上,fillna方法默认是按照列进行填充的,因此只需要使用df.fillna(df.mean())即可。括号中不传入任何参数表示按照默认的列进行计算。

0