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:如何用中位数逐列替换缺失值的主要内容,如果未能解决你的问题,请参考以下文章

为分类算法准备数据

如何用相邻值替换数据框中的 NA(缺失值)

Csr 矩阵:如何用 np.nan 而不是 0 替换缺失值?

特征工程之缺失值与离群值处理

如何用EXCEL随机生成一定位数的字符串

python数据挖掘分析清洗——缺失值处理方法汇总