Вменение данных с fancyimpute и pandas
У меня есть большая слава данных панд df
. У него немало промахов. Сброс строки/или по кол-ву не вариант. Вменение медиан, средств или наиболее частых значений также не вариант (следовательно, вменение с помощью pandas
и/или scikit
к сожалению, не scikit
).
Я наткнулся на то, что кажется аккуратным пакетом под названием fancyimpute
(вы можете найти его здесь). Но у меня есть некоторые проблемы с этим.
Вот что я делаю:
#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
. Поэтому я преобразовал df_numeric
в массив с помощью as_matrix()
.
# 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))
Выходные данные представляют собой фрейм данных с пропущенными метками столбцов. Есть ли способ получить ярлыки?
Ответы
Ответ 1
df=pd.DataFrame(data=mice.complete(d), columns=d.columns, index=d.index)
np.array
, возвращаемый методом .complete()
объекта fancyimpute (будь то мыши или KNN), подается как содержимое (argument data=)
фрейма pandas, чьи столбцы и индексы такие же, как и исходный фрейм данных.
Ответ 2
Добавьте следующие строки после кода:
df_filled.columns = df_numeric.columns
df_filled.index = df_numeric.index
Ответ 3
Я вижу разочарование от причудливого вменения и панд. Вот довольно простая оболочка, использующая метод рекурсивного переопределения. Принимает и выводит фрейм данных - имена столбцов не повреждены. Эти обертки хорошо работают с конвейерами.
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)
Ответ 4
Могу ли я получить код для вменения недостающих данных с использованием KNN в Python
Ответ 5
Я действительно ценю подход @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