使用 fancyimpute 和 pandas 进行数据插补
Data imputation with fancyimpute and pandas
我有很大的 pandas 数据名气 df
。它有很多缺失。删除 row/or col-wise 不是一个选项。估算中位数、均值或最频繁的值也不是一种选择(因此不幸的是,使用 pandas
and/or scikit
进行估算并不能解决问题)。
我发现了一个名为 fancyimpute
的简洁软件包(您可以找到它 here)。但是我有一些问题。
我是这样做的:
#the neccesary imports
import pandas as pd
import numpy as np
from fancyimpute import KNN
# df is my data frame with the missings. I keep only floats
df_numeric = = df.select_dtypes(include=[np.float])
# I now run fancyimpute KNN,
# it returns a np.array which I store as a pandas dataframe
df_filled = pd.DataFrame(KNN(3).complete(df_numeric))
然而,df_filled
不知何故是一个单一的矢量,而不是填充的数据框。如何通过插补获取数据框?
更新
我意识到,fancyimpute
需要 numpay array
。因此,我使用 as_matrix()
将 df_numeric
转换为数组。
# df is my data frame with the missings. I keep only floats
df_numeric = df.select_dtypes(include=[np.float]).as_matrix()
# I now run fancyimpute KNN,
# it returns a np.array which I store as a pandas dataframe
df_filled = pd.DataFrame(KNN(3).complete(df_numeric))
输出是一个缺少列标签的数据框。有什么方法可以检索标签?
在您的代码后添加以下行:
df_filled.columns = df_numeric.columns
df_filled.index = df_numeric.index
df=pd.DataFrame(data=mice.complete(d), columns=d.columns, index=d.index)
fancyimpute 对象(无论是 mice 还是 KNN)的 .complete()
方法返回的 np.array
作为 pandas 的内容 (argument data=)
提供列和索引与原始数据框相同的数据框。
我看到了对花哨的归咎和 pandas 的失望。这是一个使用递归覆盖方法的相当基本的包装器。接收并输出一个数据框——列名完好无损。这些类型的包装器与管道配合得很好。
from fancyimpute import SoftImpute
class SoftImputeDf(SoftImpute):
"""DataFrame Wrapper around SoftImpute"""
def __init__(self, shrinkage_value=None, convergence_threshold=0.001,
max_iters=100,max_rank=None,n_power_iterations=1,init_fill_method="zero",
min_value=None,max_value=None,normalizer=None,verbose=True):
super(SoftImputeDf, self).__init__(shrinkage_value=shrinkage_value,
convergence_threshold=convergence_threshold,
max_iters=max_iters,max_rank=max_rank,
n_power_iterations=n_power_iterations,
init_fill_method=init_fill_method,
min_value=min_value,max_value=max_value,
normalizer=normalizer,verbose=False)
def fit_transform(self, X, y=None):
assert isinstance(X, pd.DataFrame), "Must be pandas dframe"
for col in X.columns:
if X[col].isnull().sum() < 10:
X[col].fillna(0.0, inplace=True)
z = super(SoftImputeDf, self).fit_transform(X.values)
return pd.DataFrame(z, index=X.index, columns=X.columns)
我真的很欣赏@jander081 的方法,并对其进行了一点扩展以处理设置分类列。我有一个问题,分类列在训练期间会被取消设置并产生错误,所以修改代码如下:
from fancyimpute import SoftImpute
import pandas as pd
class SoftImputeDf(SoftImpute):
"""DataFrame Wrapper around SoftImpute"""
def __init__(self, shrinkage_value=None, convergence_threshold=0.001,
max_iters=100,max_rank=None,n_power_iterations=1,init_fill_method="zero",
min_value=None,max_value=None,normalizer=None,verbose=True):
super(SoftImputeDf, self).__init__(shrinkage_value=shrinkage_value,
convergence_threshold=convergence_threshold,
max_iters=max_iters,max_rank=max_rank,
n_power_iterations=n_power_iterations,
init_fill_method=init_fill_method,
min_value=min_value,max_value=max_value,
normalizer=normalizer,verbose=False)
def fit_transform(self, X, y=None):
assert isinstance(X, pd.DataFrame), "Must be pandas dframe"
for col in X.columns:
if X[col].isnull().sum() < 10:
X[col].fillna(0.0, inplace=True)
z = super(SoftImputeDf, self).fit_transform(X.values)
df = pd.DataFrame(z, index=X.index, columns=X.columns)
cats = list(X.select_dtypes(include='category'))
df[cats] = df[cats].astype('category')
# return pd.DataFrame(z, index=X.index, columns=X.columns)
return df
我有很大的 pandas 数据名气 df
。它有很多缺失。删除 row/or col-wise 不是一个选项。估算中位数、均值或最频繁的值也不是一种选择(因此不幸的是,使用 pandas
and/or scikit
进行估算并不能解决问题)。
我发现了一个名为 fancyimpute
的简洁软件包(您可以找到它 here)。但是我有一些问题。
我是这样做的:
#the neccesary imports
import pandas as pd
import numpy as np
from fancyimpute import KNN
# df is my data frame with the missings. I keep only floats
df_numeric = = df.select_dtypes(include=[np.float])
# I now run fancyimpute KNN,
# it returns a np.array which I store as a pandas dataframe
df_filled = pd.DataFrame(KNN(3).complete(df_numeric))
然而,df_filled
不知何故是一个单一的矢量,而不是填充的数据框。如何通过插补获取数据框?
更新
我意识到,fancyimpute
需要 numpay array
。因此,我使用 as_matrix()
将 df_numeric
转换为数组。
# df is my data frame with the missings. I keep only floats
df_numeric = df.select_dtypes(include=[np.float]).as_matrix()
# I now run fancyimpute KNN,
# it returns a np.array which I store as a pandas dataframe
df_filled = pd.DataFrame(KNN(3).complete(df_numeric))
输出是一个缺少列标签的数据框。有什么方法可以检索标签?
在您的代码后添加以下行:
df_filled.columns = df_numeric.columns
df_filled.index = df_numeric.index
df=pd.DataFrame(data=mice.complete(d), columns=d.columns, index=d.index)
fancyimpute 对象(无论是 mice 还是 KNN)的 .complete()
方法返回的 np.array
作为 pandas 的内容 (argument data=)
提供列和索引与原始数据框相同的数据框。
我看到了对花哨的归咎和 pandas 的失望。这是一个使用递归覆盖方法的相当基本的包装器。接收并输出一个数据框——列名完好无损。这些类型的包装器与管道配合得很好。
from fancyimpute import SoftImpute
class SoftImputeDf(SoftImpute):
"""DataFrame Wrapper around SoftImpute"""
def __init__(self, shrinkage_value=None, convergence_threshold=0.001,
max_iters=100,max_rank=None,n_power_iterations=1,init_fill_method="zero",
min_value=None,max_value=None,normalizer=None,verbose=True):
super(SoftImputeDf, self).__init__(shrinkage_value=shrinkage_value,
convergence_threshold=convergence_threshold,
max_iters=max_iters,max_rank=max_rank,
n_power_iterations=n_power_iterations,
init_fill_method=init_fill_method,
min_value=min_value,max_value=max_value,
normalizer=normalizer,verbose=False)
def fit_transform(self, X, y=None):
assert isinstance(X, pd.DataFrame), "Must be pandas dframe"
for col in X.columns:
if X[col].isnull().sum() < 10:
X[col].fillna(0.0, inplace=True)
z = super(SoftImputeDf, self).fit_transform(X.values)
return pd.DataFrame(z, index=X.index, columns=X.columns)
我真的很欣赏@jander081 的方法,并对其进行了一点扩展以处理设置分类列。我有一个问题,分类列在训练期间会被取消设置并产生错误,所以修改代码如下:
from fancyimpute import SoftImpute
import pandas as pd
class SoftImputeDf(SoftImpute):
"""DataFrame Wrapper around SoftImpute"""
def __init__(self, shrinkage_value=None, convergence_threshold=0.001,
max_iters=100,max_rank=None,n_power_iterations=1,init_fill_method="zero",
min_value=None,max_value=None,normalizer=None,verbose=True):
super(SoftImputeDf, self).__init__(shrinkage_value=shrinkage_value,
convergence_threshold=convergence_threshold,
max_iters=max_iters,max_rank=max_rank,
n_power_iterations=n_power_iterations,
init_fill_method=init_fill_method,
min_value=min_value,max_value=max_value,
normalizer=normalizer,verbose=False)
def fit_transform(self, X, y=None):
assert isinstance(X, pd.DataFrame), "Must be pandas dframe"
for col in X.columns:
if X[col].isnull().sum() < 10:
X[col].fillna(0.0, inplace=True)
z = super(SoftImputeDf, self).fit_transform(X.values)
df = pd.DataFrame(z, index=X.index, columns=X.columns)
cats = list(X.select_dtypes(include='category'))
df[cats] = df[cats].astype('category')
# return pd.DataFrame(z, index=X.index, columns=X.columns)
return df