Python Pandas Fillna 中位数不起作用
Posted
技术标签:
【中文标题】Python Pandas Fillna 中位数不起作用【英文标题】:Python Pandas Fillna Median not working 【发布时间】:2018-08-14 03:18:03 【问题描述】:我正在尝试在包含多列和多行的数据框中填充所有 nan。我正在使用它来训练多变量 ML 模型,所以我想用中位数填充每列的 nans。只是为了测试中值函数,我这样做了:
training_df.loc[[0]] = np.nan # Sets first row to nan
print(training_df.isnull().values.any()) # Prints true because we just inserted nans
test = training_df.fillna(training_df.median()) # Fillna with median
print(test.isnull().values.any()) # Check afterwards
但是当我这样做时,没有任何反应,最后一行的打印仍然返回 True。如果我尝试更改为使用这样的中值函数:
training_df.fillna(training_df.median(), inplace=True)
什么也没有发生。如果我这样做:
training_df = training_df.fillna(training_df.median(), inplace=True)
Training_df 变为无。我该如何解决这个问题?
【问题讨论】:
我要做的第一件事是使用training_df.info()
检查training_df
的数据类型。如果您有任何未存储为数字类型的列,则可能会发生您所描述的行为。
另外,当您使用inplace=True
时,不要将结果分配给变量,因为它始终是None
。这就是为什么你的最后一行将整个变量设置为None
。
【参考方案1】:
正如@thesilkworm 建议的那样,首先将您的系列转换为数字。下面是一个最小的例子:
import pandas as pd, numpy as np
df = pd.DataFrame([[np.nan, np.nan, np.nan],
[5, 1, 2, 'hello'],
[1, 4, 3, 4],
[9, 8, 7, 6]], dtype=object)
df = df.fillna(df.median()) # fails
df[df.columns] = df[df.columns].apply(pd.to_numeric, errors='coerce')
df = df.fillna(df.median()) # works
【讨论】:
【参考方案2】:您可以使用np.nanmedian
+ 字典推导来重命名。
df = pd.DataFrame("col1": [1,2,np.nan,3], "col2": [5, np.nan, 10, np.nan])
col_map = df.columns.get_loc(col):col for col in df.columns # 0: "col1", 1: "col2"
median_values = pd.Series(np.nanmedian(df, axis=0)).rename(col_map)
df = df.fillna(median_values)
>> df
col1 col2
0 1.0 5.0
1 2.0 7.5
2 2.0 10.0
3 3.0 7.5
您可以看到 jpp 在.apply()
之后调用df.median()
的答案中的间歇步骤与我上面定义的median_series
相同。
print(df.median()) # after .apply()
col1 2.0
col2 7.5
dtype: float64
print(median_series)
col1 2.0
col2 7.5
dtype: float64
注意:如果您的 df 中的某个值是我们在生产中经常需要的“hi”之类的字符串,则使用 np.nanmedian
会出错。
解释:
在大多数情况下,我仍然喜欢 jpp 的答案,但有时如果我的数据很大或者我正在将数据发送到 ML API 端点,我不想使用 errors='coerce'
来覆盖所有内容并做 想要返回错误。想象一下您在 6 个月后投入生产的场景,并且您的一些 col1
值作为字符串传递:[1, 2, 'hi', 'bye']
。使用errors=coerce
会将hi
和bye
设置为NaN
。您将不会意识到字符串从您未进行的某些上游更改泄漏到列中,并且您的 ML 算法正在像正常一样传递分数,但实际上它只是对一堆 NaN 进行评分。您的模型性能会在不知道原因的情况下下降,实际上它是一个很好的模型,它只是没有对正确的数据进行评分。公司赔钱,你就被解雇了。我意识到我偏离了一个不太可能的滑坡,但想强调重点。
我们想要如果在 prod 中出现此错误:
df = pd.DataFrame("col1": [1,2,np.nan,'hi'], "col2": [5, np.nan, 10, np.nan])
col_map = df.columns.get_loc(col):col for col in df.columns # 0: "col1", 1: "col2"
median_series = pd.Series(np.nanmedian(df, axis=0)).rename(col_map)
>> TypeError: ufunc 'isnan' not supported for the input types, and the inputs
could not be safely coerced to any supported types according to the casting rule ''safe''
【讨论】:
以上是关于Python Pandas Fillna 中位数不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Python pandas 使用 fillna() 来避免对 NaN 值进行错误拆分