Python 用FANYIMPUTE和pandas进行数据插补

Python 用FANYIMPUTE和pandas进行数据插补,python,python-3.x,pandas,imputation,fancyimpute,Python,Python 3.x,Pandas,Imputation,Fancyimpute,我有一个大熊猫数据名df。它有相当多的缺失。删除行/列不是一个选项。输入中间值、平均值或最频繁的值也不是一个选项(因此,使用pandas和/或scikit进行插补不幸没有起到作用) 我遇到了一个看起来很整洁的软件包,叫做fancyicomputer(你可以找到它)。但是我有一些问题 以下是我的工作: #the neccesary imports import pandas as pd import numpy as np from fancyimpute import KNN # df is

我有一个大熊猫数据名
df
。它有相当多的缺失。删除行/列不是一个选项。输入中间值、平均值或最频繁的值也不是一个选项(因此,使用
pandas
和/或
scikit
进行插补不幸没有起到作用)

我遇到了一个看起来很整洁的软件包,叫做
fancyicomputer
(你可以找到它)。但是我有一些问题

以下是我的工作:

#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
在某种程度上是单个向量,而不是填充的数据帧。如何通过插补获得数据帧

更新 我意识到,
fancyicomputer
需要一个
numpay数组
。因此,我使用
as_matrix()
df_numeric
转换为数组


输出是列标签丢失的数据帧。有没有办法检索标签?

在代码后添加以下行:

df_filled.columns = df_numeric.columns
df_filled.index = df_numeric.index

FancyComputer对象(无论是mice还是KNN)的
.complete()
方法返回的
np.array
作为pandas数据帧的内容
(参数数据=)
,其COL和索引与原始数据帧相同。

我看到了fancy Inpute和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)

来自FancyComputer导入软件输入
软插补F类(软插补):
“”“软插补周围的数据帧包装器”“”
def uuu init uuuu(自,收缩u值=无,收敛u阈值=0.001,
max\u iters=100,max\u rank=None,n\u power\u iterations=1,init\u fill\u method=“零”,
最小值=无,最大值=无,规格化器=无,详细值=真):
super(软输入f,self)。\uuuu init\uuuuu(收缩值=收缩值,
收敛阈值=收敛阈值,
最高等级=最高等级,最高等级=最高等级,
n次幂次迭代=n次幂次迭代,
init_fill_method=init_fill_method,
最小值=最小值,最大值=最大值,
normalizer=normalizer,verbose=False)
def fit_变换(self,X,y=None):
断言isinstance(X,pd.DataFrame),“必须是dframe”
对于X列中的列:
如果X[col].isnull().sum()小于10:
X[col].fillna(0.0,原地=真)
z=super(软输入f,自)。拟合_变换(X.values)
返回pd.DataFrame(z,index=X.index,columns=X.columns)

我非常欣赏@jander081的方法,并对其进行了一点扩展,以处理设置分类列的问题。我遇到了一个问题,即分类列在培训期间会被取消设置并产生错误,因此对代码进行了如下修改:

来自FancyComputer导入软件输入
作为pd进口熊猫
软插补F类(软插补):
“”“软插补周围的数据帧包装器”“”
def uuu init uuuu(自,收缩u值=无,收敛u阈值=0.001,
max\u iters=100,max\u rank=None,n\u power\u iterations=1,init\u fill\u method=“零”,
最小值=无,最大值=无,规格化器=无,详细值=真):
super(软输入f,self)。\uuuu init\uuuuu(收缩值=收缩值,
收敛阈值=收敛阈值,
最高等级=最高等级,最高等级=最高等级,
n次幂次迭代=n次幂次迭代,
init_fill_method=init_fill_method,
最小值=最小值,最大值=最大值,
normalizer=normalizer,verbose=False)
def fit_变换(self,X,y=None):
断言isinstance(X,pd.DataFrame),“必须是dframe”
对于X列中的列:
如果X[col].isnull().sum()小于10:
X[col].fillna(0.0,原地=真)
z=super(软输入f,自)。拟合_变换(X.values)
df=pd.DataFrame(z,index=X.index,columns=X.columns)
cats=列表(X.选择类型(包括class='category'))
df[cats]=df[cats].astype('category')
#返回pd.DataFrame(z,index=X.index,columns=X.columns)
返回df

谢谢你,米里亚姆!我满脑子都是在
FancyComputer
文档中找到的东西,我忘记了简单的解决方案。完美答案
df_filled.columns=df_numeric.columns
应该这样做。这看起来确实是一个有趣的包,btwI也这么认为!我对
pandas fillna()
sklearn.preprocessing.Imputer
有点失望。我没有遇到一个我可以充分利用它们的情况。我想,他们会从一些更复杂的方法中受益匪浅,这些方法可以插补缺失的数据。你能解释一下这个答案吗?当然。FancyComputer对象(无论是mice还是KNN)的.complete()方法返回的np.array作为pandas数据帧的内容(参数data=)提供,该数据帧的COL和索引与原始数据帧相同。当我调用fit_transform方法时,我应该向它传递哪些参数来插补它,我使用的是CSV文件
df=pd.DataFrame(data=mice.complete(d), columns=d.columns, index=d.index)
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)