Python 在scikit学习中输入类别缺失值
我有一些文本类型的列的数据。这些文本列中有一些NaN值。我想做的是通过Python 在scikit学习中输入类别缺失值,python,pandas,scikit-learn,imputation,Python,Pandas,Scikit Learn,Imputation,我有一些文本类型的列的数据。这些文本列中有一些NaN值。我想做的是通过sklearn.preprocessing.Imputer(用最频繁的值替换NaN)来插补这些NaN。问题在执行中。 假设有一个包含30列的熊猫数据帧df,其中10列属于分类性质。 一旦我跑步: from sklearn.preprocessing import Imputer imp = Imputer(missing_values='NaN', strategy='most_frequent', axis=0) imp.f
sklearn.preprocessing.Imputer
(用最频繁的值替换NaN)来插补这些NaN。问题在执行中。
假设有一个包含30列的熊猫数据帧df,其中10列属于分类性质。
一旦我跑步:
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='most_frequent', axis=0)
imp.fit(df)
Python生成一个错误:“无法将字符串转换为float:“run1”
,其中“run1”是第一列中包含分类数据的普通(非缺失)值
class CustomImputer(BaseEstimator, TransformerMixin):
def __init__(self, strategy='mean',filler='NA'):
self.strategy = strategy
self.fill = filler
def fit(self, X, y=None):
if self.strategy in ['mean','median']:
if not all(X.dtypes == np.number):
raise ValueError('dtypes mismatch np.number dtype is \
required for '+ self.strategy)
if self.strategy == 'mean':
self.fill = X.mean()
elif self.strategy == 'median':
self.fill = X.median()
elif self.strategy == 'mode':
self.fill = X.mode().iloc[0]
elif self.strategy == 'fill':
if type(self.fill) is list and type(X) is pd.DataFrame:
self.fill = dict([(cname, v) for cname,v in zip(X.columns, self.fill)])
return self
def transform(self, X, y=None):
return X.fillna(self.fill)
非常欢迎任何帮助为数字列使用平均值,为非数字列使用最频繁的值,您可以这样做。您可以进一步区分整数和浮点数。我想对整型列使用中位数可能是有意义的
import pandas as pd
import numpy as np
from sklearn.base import TransformerMixin
class DataFrameImputer(TransformerMixin):
def __init__(self):
"""Impute missing values.
Columns of dtype object are imputed with the most frequent value
in column.
Columns of other types are imputed with mean of column.
"""
def fit(self, X, y=None):
self.fill = pd.Series([X[c].value_counts().index[0]
if X[c].dtype == np.dtype('O') else X[c].mean() for c in X],
index=X.columns)
return self
def transform(self, X, y=None):
return X.fillna(self.fill)
data = [
['a', 1, 2],
['b', 1, 1],
['b', 2, 2],
[np.nan, np.nan, np.nan]
]
X = pd.DataFrame(data)
xt = DataFrameImputer().fit_transform(X)
print('before...')
print(X)
print('after...')
print(xt)
它打印
before...
0 1 2
0 a 1 2
1 b 1 1
2 b 2 2
3 NaN NaN NaN
after...
0 1 2
0 a 1.000000 2.000000
1 b 1.000000 1.000000
2 b 2.000000 2.000000
3 b 1.333333 1.666667
此代码以最常见的类别填充系列:
import pandas as pd
import numpy as np
# create fake data
m = pd.Series(list('abca'))
m.iloc[1] = np.nan #artificially introduce nan
print('m = ')
print(m)
#make dummy variables, count and sort descending:
most_common = pd.get_dummies(m).sum().sort_values(ascending=False).index[0]
def replace_most_common(x):
if pd.isnull(x):
return most_common
else:
return x
new_m = m.map(replace_most_common) #apply function to original data
print('new_m = ')
print(new_m)
产出:
m =
0 a
1 NaN
2 c
3 a
dtype: object
new_m =
0 a
1 a
2 c
3 a
dtype: object
复制和修改斯维瑟的答案,我为熊猫系列对象做了一个插补器
import numpy
import pandas
from sklearn.base import TransformerMixin
class SeriesImputer(TransformerMixin):
def __init__(self):
"""Impute missing values.
If the Series is of dtype Object, then impute with the most frequent object.
If the Series is not of dtype Object, then impute with the mean.
"""
def fit(self, X, y=None):
if X.dtype == numpy.dtype('O'): self.fill = X.value_counts().index[0]
else : self.fill = X.mean()
return self
def transform(self, X, y=None):
return X.fillna(self.fill)
要使用它,请执行以下操作:
# Make a series
s1 = pandas.Series(['k', 'i', 't', 't', 'e', numpy.NaN])
a = SeriesImputer() # Initialize the imputer
a.fit(s1) # Fit the imputer
s2 = a.transform(s1) # Get a new series
类似的。修改
策略class='most_frequency'
的输入器
:
class GeneralImputer(Imputer):
def __init__(self, **kwargs):
Imputer.__init__(self, **kwargs)
def fit(self, X, y=None):
if self.strategy == 'most_frequent':
self.fills = pd.DataFrame(X).mode(axis=0).squeeze()
self.statistics_ = self.fills.values
return self
else:
return Imputer.fit(self, X, y=y)
def transform(self, X):
if hasattr(self, 'fills'):
return pd.DataFrame(X).fillna(self.fills).values.astype(str)
else:
return Imputer.transform(self, X)
其中
pandas.DataFrame.mode()
为每列查找最频繁的值,然后pandas.DataFrame.fillna()
用这些值填充缺少的值。其他策略
值仍然由插补器
以同样的方式处理,灵感来自这里的答案,并且为了所有用例都需要一个goto插补器,我最后写了这篇文章。它支持四种插补策略mean、mode、median、fill
适用于pd.DataFrame
和pd.Series
平均值
和中值
仅适用于数字数据,模式
和填充
适用于数字和分类数据
class CustomImputer(BaseEstimator, TransformerMixin):
def __init__(self, strategy='mean',filler='NA'):
self.strategy = strategy
self.fill = filler
def fit(self, X, y=None):
if self.strategy in ['mean','median']:
if not all(X.dtypes == np.number):
raise ValueError('dtypes mismatch np.number dtype is \
required for '+ self.strategy)
if self.strategy == 'mean':
self.fill = X.mean()
elif self.strategy == 'median':
self.fill = X.median()
elif self.strategy == 'mode':
self.fill = X.mode().iloc[0]
elif self.strategy == 'fill':
if type(self.fill) is list and type(X) is pd.DataFrame:
self.fill = dict([(cname, v) for cname,v in zip(X.columns, self.fill)])
return self
def transform(self, X, y=None):
return X.fillna(self.fill)
用法
>> df
MasVnrArea FireplaceQu
Id
1 196.0 NaN
974 196.0 NaN
21 380.0 Gd
5 350.0 TA
651 NaN Gd
>> CustomImputer(strategy='mode').fit_transform(df)
MasVnrArea FireplaceQu
Id
1 196.0 Gd
974 196.0 Gd
21 380.0 Gd
5 350.0 TA
651 196.0 Gd
>> CustomImputer(strategy='fill', filler=[0, 'NA']).fit_transform(df)
MasVnrArea FireplaceQu
Id
1 196.0 NA
974 196.0 NA
21 380.0 Gd
5 350.0 TA
651 0.0 Gd
您可以使用
sklearn\u pandas.categoricalComputer
进行分类列。详情:
首先,(来自《使用Scikit Learn和TensorFlow进行机器学习》一书),您可以为数字和字符串/分类功能创建子管道,其中每个子管道的第一个转换器是一个选择器,它获取列名称列表(并且full\u pipeline.fit\u transform()
获取一个数据帧):
然后,您可以将这些子管道与sklearn.pipeline.FeatureUnion
组合,例如:
full_pipeline = FeatureUnion(transformer_list=[
("num_pipeline", num_pipeline),
("cat_pipeline", cat_pipeline)
])
现在,在num_管道
中,您可以简单地使用sklearn.preprocessing.inputer()
,但在cat_管道
中,您可以从sklearn_
包中使用categoricalcomputer()
注意:sklearn pandas
软件包可以与pip安装sklearn pandas
一起安装,但它是作为import sklearn\u pandas
导入的
from sklearn.preprocessing import Imputer
impute = Imputer(strategy='mean')
for cols in ['quantitative_column', 'quant']: # here both are quantitative features.
xx[cols] = impute.fit_transform(xx[[cols]])
from sklearn.preprocessing import Imputer
from sklearn.base import TransformerMixin
class CustomImputer(TransformerMixin):
def __init__(self, cols=None, strategy='mean'):
self.cols = cols
self.strategy = strategy
def transform(self, df):
X = df.copy()
impute = Imputer(strategy=self.strategy)
if self.cols == None:
self.cols = list(X.columns)
for col in self.cols:
if X[col].dtype == np.dtype('O') :
X[col].fillna(X[col].value_counts().index[0], inplace=True)
else : X[col] = impute.fit_transform(X[[col]])
return X
def fit(self, *_):
return self
X = pd.DataFrame({'city':['tokyo', np.NaN, 'london', 'seattle', 'san
francisco', 'tokyo'],
'boolean':['yes', 'no', np.NaN, 'no', 'no', 'yes'],
'ordinal_column':['somewhat like', 'like', 'somewhat like', 'like',
'somewhat like', 'dislike'],
'quantitative_column':[1, 11, -.5, 10, np.NaN, 20]})
city boolean ordinal_column quantitative_column
0 tokyo yes somewhat like 1.0
1 NaN no like 11.0
2 london NaN somewhat like -0.5
3 seattle no like 10.0
4 san francisco no somewhat like NaN
5 tokyo yes dislike 20.0
cci = CustomImputer(cols=['city', 'boolean']) # here default strategy = mean
cci.fit_transform(X)
sd = CustomImputer(['quantitative_column'], strategy = 'median')
sd.fit_transform(X)
call = CustomImputer()
call.fit_transform(X)
有一个包
sk
,它可以选择对分类变量进行插补
您可以尝试以下方法:
replace = df.<yourcolumn>.value_counts().argmax()
df['<yourcolumn>'].fillna(replace, inplace=True)
replace=df..value_counts().argmax()
df['').fillna(替换,就地=真)
sklearn.impute.SimpleImputer代替Imputer可以很容易地解决这个问题,它可以处理分类变量
根据Sklearn文档:
如果为“最频繁”,则使用每列最频繁的值替换缺失。可用于字符串或数字数据
inputer
处理数字,而不是字符串。转换为数字,然后输入,然后再转换回来。有没有合适的方法通过scikit learn将其自动化?为什么它不允许对最常用的策略使用分类变量?奇怪。您现在可以从sklearn.inpute导入SimpleInputer然后使用imp=SimpleInputer(missing_values=np.nan,strategy='most_frequency')
做得很好。我将在:)中使用您的代码片段。如果您有任何进一步的建议,我很乐意听到。这很好,但是如果任何列都有所有的nan值,它将不起作用。这些所有的nan列都应该从DF中删除。很好:)我将使用它,但将其稍作修改,使其在GridSearchCV中使用时,对浮点使用均值,对整数使用中值,字符串的模式DataFrameInputer()不具有get_params()属性。修复方法是从sklearn.base.BaseEstimator
继承。@mamun类提供了fit\u transform
方法。我支持这个答案;pypi网站上的官方sklearn pandas文档提到了这一点:“分类计算机由于scikit learn输入转换器目前仅适用于数字,因此sklearn pandas提供了一个等效的辅助转换器,可以处理字符串,用该列中最频繁的值替换空值。”这是包裹上的。
replace = df.<yourcolumn>.value_counts().argmax()
df['<yourcolumn>'].fillna(replace, inplace=True)
impute_size=SimpleImputer(strategy="most_frequent")
data['Outlet_Size']=impute_size.transform(data[['Outlet_Size']])