パイプラインのデータを消去するために、sklearn
に一連のカスタム変換を書きます。各カスタム変換では、fit
とtransform
のパラメータとして2つのPandas DataFrameが使用され、transform
は2つのデータフレームも返します(下記の例を参照)。 DataFrames inとDataFrames out:パイプラインにトランスフォーマが1つしかない場合、これはうまく動作します。このような両方のRransformersがパイプラインに結合されるが sklearnのどのデータが変換されますか?
、:不思議な入力としてタプルを受け取るRemoveMissingRowsBasedOnTarget
pipeline = Pipeline ([
('remove_missing_columns', RemoveAllMissing (['mailing_address_str_number'])),
('remove_rows_based_on_target', RemoveMissingRowsBasedOnTarget()),
])
X, y = pipeline.fit_transform (X, y)
==>TypeError: tuple indices must be integers or slices, not Series
クラス。私はこの
pipeline = Pipeline ([
('remove_rows_based_on_target', RemoveMissingRowsBasedOnTarget()),
('remove_missing_columns', RemoveAllMissing (['mailing_address_str_number'])),
])
==> AttributeError: 'tuple' object has no attribute 'apply'
のような変圧器の位置を切り替えるとエラーがクラスRemoveAllMissing
で発生します。どちらの場合も、エラーが発生した行の上に==>というエラーメッセージが表示されます。私は正確に何が起こっているのか正確に何かを読んだことがあると思うが、私はこの問題について何も見つけることができなかった。誰かが私が間違っていることを教えてもらえますか?以下は、問題のコードを分離したものです。
import numpy as np
import pandas as pd
import random
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
def create_data (rows, cols, frac_nan, random_state=42):
random.seed (random_state)
X = pd.DataFrame (np.zeros ((rows, cols)),
columns=['col' + str(i) for i in range (cols)],
index=None)
# Create dataframe of (rows * cols) with random floating points
y = pd.DataFrame (np.zeros ((rows,)))
for row in range(rows):
for col in range(cols):
X.iloc [row,col] = random.random()
X.iloc [row,1] = np.nan # column 1 exists colely of NaN's
y.iloc [row] = random.randint (0, 1)
# Assign NaN's to a fraction of X
n = int(frac_nan * rows * cols)
for i in range (n):
row = random.randint (0, rows-1)
col = random.randint (0, cols-1)
X.iloc [row, col] = np.nan
# Same applies to y
n = int(frac_nan * rows)
for i in range (n):
row = random.randint (0, rows-1)
y.iloc [row,] = np.nan
return X, y
class RemoveAllMissing (BaseEstimator, TransformerMixin):
# remove columns containg NaN only
def __init__ (self, requested_cols=[]):
self.all_missing_data = requested_cols
def fit (self, X, y=None):
# find empty columns == columns with all missing data
missing_cols = X.apply (lambda x: x.count(), axis=0)
for idx in missing_cols.index:
if missing_cols [idx] == 0:
self.all_missing_data.append (idx)
return self
def transform (self, X, y=None):
print (">RemoveAllMissing - X shape: " + str (X.shape), " y shape: " + str (y.shape), 'type (X):', type(X))
for all_missing_predictor in self.all_missing_data:
del X [all_missing_predictor]
print ("<RemoveAllMissing - X shape: " + str (X.shape), " y shape: " + str (y.shape), 'type (X):', type(X))
return X, y
def fit_transform (self, X, y=None):
return self.fit (X, y).transform (X, y)
class RemoveMissingRowsBasedOnTarget (BaseEstimator, TransformerMixin):
# remove each row where target contains one or more NaN's
def __init__ (self):
self.missing_rows = []
def fit (self, X, y = None):
# remove all rows where the target value is missing data
print (type (X))
if y is None:
print ('RemoveMissingRowsBasedOnTarget: target (y) cannot be None')
return self
self.missing_rows = np.array (y.notnull()) # false = missing data
return self
def transform (self, X, y=None):
print (">RemoveMissingRowsBasedOnTarget - X shape: " + str (X.shape), " y shape: " + str (y.shape), 'type (X):', type(X))
if y is None:
print ('RemoveMissingRowsBasedOnTarget: target (y) cannot be None')
return X, y
X = X [self.missing_rows].reset_index()
del X ['index']
y = y [self.missing_rows].reset_index()
del y ['index']
print ("<RemoveMissingRowsBasedOnTarget - X shape: " + str (X.shape), " y shape: " + str (y.shape), 'type (X):', type(X))
return X, y
def fit_transform (self, X, y=None):
return self.fit (X, y).transform (X, y)
pipeline = Pipeline ([
('RemoveAllMissing', RemoveAllMissing()),
('RemoveMissingRowsBasedOnTarget', RemoveMissingRowsBasedOnTarget()),
])
X, y = create_data (25, 10, 0.1)
print ("X shape: " + str (X.shape), " y shape: " + str (y.shape), 'type (X):', type(X))
X, y = pipeline.fit_transform (X, y)
#X, y = RemoveAllMissing().fit_transform (X, y)
#X, y = RemoveMissingRowsBasedOnTarget().fit_transform (X, y)
@Vivekとして編集は、私は問題が特定されると実行されますが、スタンドアロンコードによって、元のコードを交換した要求しました。タプルはDataFrameではなくパラメータとして転送されるため、コードはそのままの状態でクラッシュします。パイプラインによってデータ型が変更され、ドキュメントにそのデータ型が見つかりません。 1は、パイプラインへの呼び出しをコメントアウトし、このように、正常に動作しますeveryting変圧器の別の呼び出しの前にコメントを削除する場合:
#X, y = pipeline.fit_transform (X, y)
X, y = RemoveAllMissing().fit_transform (X, y)
X, y = RemoveMissingRowsBasedOnTarget().fit_transform (X, y)
:また、私はあなたが見てすることができますパイプライン内のターゲット変数を
y
変換するためのいくつかの関連する問題があることがわかりましたprint(type(X)) 'その時点で印刷しますか?(クラス 'RemoveMissingRowsBasedOnTarget'、最初に呼び出されたとき) ' X'は次のクラス( 'RemoveAllMissing')を呼び出すためにDataFrameでなければならないが、その時点ではタプルになったようだ... – Eskappそれは依存する呼び出しの順序:RemoveMissingRowsBasedOnTargetが最初に呼び出されるとDataFrameが印刷され、2番目に呼び出されるとタプルが印刷されます。エラーメッセージは、rfeferredメソッドを持たないタプルについても不平を言っています。 – Arnold
サンプルデータと一緒にコードを簡単にコピーしてください。 –