pandasテキストタイプのいくつかの列を持つデータがあります。これらのテキスト列と一緒にいくつかのNaN値があります。私がやろうとしているのは、sklearn.preprocessing.Imputer
(NaNを最も頻度の高い値に置き換えます。問題は実装にあります。Pandas 30列のデータフレームdfがあり、そのうち10がカテゴリの性質です。実行したら:
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='most_frequent', axis=0)
imp.fit(df)
Pythonはerror: 'could not convert string to float: 'run1''
を生成します。ここで、「run1」は、カテゴリデータを含む最初の列からの通常の(欠損がない)値です。
どんな助けでも大歓迎です
数値列に平均値を使用し、非数値列に最も頻繁に使用する値を使用するには、次のようにします。整数と浮動小数点をさらに区別できます。代わりに整数列の中央値を使用するのが理にかなっていると思います。
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
カテゴリー列には_sklearn_pandas.CategoricalImputer
_を使用できます。詳細:
まず、(Scikit-LearnおよびTensorFlowを使用したハンズオン機械学習の書籍から)数値および文字列/カテゴリの機能のサブパイプラインを使用できます。各サブパイプラインの最初のトランスフォーマーは、列名のリスト(およびfull_pipeline.fit_transform()
はpandas DataFrame)を取ります:
_class DataFrameSelector(BaseEstimator, TransformerMixin):
def __init__(self, attribute_names):
self.attribute_names = attribute_names
def fit(self, X, y=None):
return self
def transform(self, X):
return X[self.attribute_names].values
_
次に、これらのサブパイプラインを_sklearn.pipeline.FeatureUnion
_と組み合わせることができます。次に例を示します。
_full_pipeline = FeatureUnion(transformer_list=[
("num_pipeline", num_pipeline),
("cat_pipeline", cat_pipeline)
])
_
現在、_num_pipeline
_ではsklearn.preprocessing.Imputer()
を使用できますが、_cat_pipline
_では、_sklearn_pandas
_パッケージのCategoricalImputer()
を使用できます。
注: _sklearn-pandas
_パッケージは_pip install sklearn-pandas
_でインストールできますが、_import sklearn_pandas
_としてインポートされます
Sveitserの答えをコピーして変更し、pandas.Seriesオブジェクトのimputerを作成しました
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
パッケージがありますsklearn-pandas
カテゴリ変数の代入のオプションがあります https://github.com/scikit-learn-contrib/sklearn-pandas#categoricalimputer
>>> from sklearn_pandas import CategoricalImputer
>>> data = np.array(['a', 'b', 'b', np.nan], dtype=object)
>>> imputer = CategoricalImputer()
>>> imputer.fit_transform(data)
array(['a', 'b', 'b', 'b'], dtype=object)
ここでの答えに触発され、すべてのユースケースでgoto Imputerが必要であるため、私はこれを書きました。代入の4つの戦略mean, mode, median, fill
は両方で機能しますpd.DataFrame
およびPd.Series
。
mean
およびmedian
は数値データに対してのみ機能し、mode
およびfill
は数値データとカテゴリデータの両方に対して機能します。
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
strategy = 'most_frequent'は、定性的ではなく、定量的機能でのみ使用できます。このカスタムインピュアは、定性的および定量的の両方に使用できます。また、scikit学習インプターでは、データフレーム全体に使用するか(すべての機能が定量的である場合)、または類似タイプの機能/列のリストで「forループ」を使用できます(以下の例を参照)。ただし、カスタム入力は任意の組み合わせで使用できます。
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
1)同様のタイプの機能のリストで使用できます。
cci = CustomImputer(cols=['city', 'boolean']) # here default strategy = mean
cci.fit_transform(X)
strategy = medianで使用できます
sd = CustomImputer(['quantitative_column'], strategy = 'median')
sd.fit_transform(X)
3)データフレーム全体で使用できます。デフォルトの平均値を使用します(または中央値で変更することもできます。定性的な機能の場合はstrategy = 'most_frequent'を使用し、定量的な平均値/中央値を使用します。
call = CustomImputer()
call.fit_transform(X)
このコードは、最も頻繁なカテゴリでシリーズを埋めます:
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
同様。 _strategy='most_frequent'
_のImputer
を変更します。
_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()
は欠損値をこれらの値で埋めます。他のstrategy
値は、Imputer
によって引き続き同じ方法で処理されます。