Python:如何用中位数逐列替换缺失值
Posted
技术标签:
【中文标题】Python:如何用中位数逐列替换缺失值【英文标题】:Python: How to replace missing values column wise by median 【发布时间】:2019-07-19 15:34:35 【问题描述】:我有一个如下的数据框
df = pd.DataFrame('A': [1, 2, 3], 'B': [1.45, 2.33, np.nan], 'C': [4, 5, 6], 'D': [4.55, 7.36, np.nan])
我想以通用方式替换缺失值,即np.nan
。为此,我创建了如下函数
def treat_mis_value_nu(df):
df_nu = df.select_dtypes(include=['number'])
lst_null_col = df_nu.columns[df_nu.isnull().any()].tolist()
if len(lst_null_col)>0:
for i in lst_null_col:
if df_nu[i].isnull().sum()/len(df_nu[i])>0.10:
df_final_nu = df_nu.drop([i],axis=1)
else:
df_final_nu = df_nu[i].fillna(df_nu[i].median(),inplace=True)
return df_final_nu
当我如下应用此功能时
df_final = treat_mis_value_nu(df)
我得到如下数据框
A B C
0 1 1.0 4
1 2 2.0 5
2 3 NaN 6
所以它实际上已正确删除列D
,但未能删除列B
。
我知道过去已经讨论过这个话题(here)。还是我可能遗漏了什么?
【问题讨论】:
您能否发表声明,解释您想要在您的generic
函数中实现什么?
【参考方案1】:
用途:
df = pd.DataFrame('A': [1, 2, 3,5,7], 'B': [1.45, 2.33, np.nan, np.nan, np.nan],
'C': [4, 5, 6,8,7], 'D': [4.55, 7.36, np.nan,9,10],
'E':list('abcde'))
print (df)
A B C D E
0 1 1.45 4 4.55 a
1 2 2.33 5 7.36 b
2 3 NaN 6 NaN c
3 5 NaN 8 9.00 d
4 7 NaN 7 10.00 e
def treat_mis_value_nu(df):
#get only numeric columns to dataframe
df_nu = df.select_dtypes(include=['number'])
#get only columns with NaNs
df_nu = df_nu.loc[:, df_nu.isnull().any()]
#get columns for remove with mean instead sum/len, it is same
cols_to_drop = df_nu.columns[df_nu.isnull().mean() <= 0.30]
#replace missing values of original columns and remove above thresh
return df.fillna(df_nu.median()).drop(cols_to_drop, axis=1)
print (treat_mis_value_nu(df))
A C D E
0 1 4 4.55 a
1 2 5 7.36 b
2 3 6 8.18 c
3 5 8 9.00 d
4 7 7 10.00 e
【讨论】:
嗨@jezrael:这很好。只是另一个相关查询;如果上面示例中的列包含string
,那么我想将nan
替换为blank
。我已将函数的最后一行更改为return df.fillna('blank').drop(cols_to_drop, axis=1)
。但这不起作用。 IE。我仍然在df
中收到nan
。请让我知道如何解决这个问题。
@pythondumb - 嗯,所以不工作return df.fillna(df_nu.median()).drop(cols_to_drop, axis=1).fillna('blank')
?也许需要return df.fillna(df_nu.median()).drop(cols_to_drop, axis=1).replace('NaN', 'blank')
让我检查一下。此外我不能做df.apply(lambda x:f(x))
操作。这里f(x)
只不过是一个简单的正则表达式re.sub('[^A-Za-z0-9]', ' ', text)
。我是否需要将特定列(如您的示例中的E
col)转换为astype(str)
?
@pythondumb - 不确定是否理解不足,你能用更改数据显示它吗?【参考方案2】:
我建议查看 sklearn Imputer transformer。我不认为它可以删除列,但它可以明确地以“通用方式”填充它们 - 例如,用相关列的中位数填充缺失值。
你可以这样使用它:
from sklearn.preprocessing import Imputer
imputer = Imputer(strategy='median')
num_df = df.values
names = df.columns.values
df_final = pd.DataFrame(imputer.transform(num_df), columns=names)
如果您想进行其他转换,可以考虑进行转换Pipeline,甚至可以制作自己的转换器来执行定制任务。
【讨论】:
以上是关于Python:如何用中位数逐列替换缺失值的主要内容,如果未能解决你的问题,请参考以下文章