Pandasにget_dummies()があるのは本当に素晴らしいですが、機械学習に役立つためには、train / testフレームワーク(またはsklearnの用語では「fit_transform」と「transform」)で使用できる必要があります。 さらに説明が必要な場合はお知らせください。
だから、これはパンダにその機能を追加するためのウィッシュリストのバグレポートだと思います。 プルリクエストを作成することもできます。これがパンダで役立つものであることに人々が同意した場合(そして、このプロジェクトへの私の最初の貢献となるものについて少し指導し、コードレビューを行う用意があります)。
サンプルフレームからの入力と出力を使用した擬似コードの例はどうでしょうか。
@ chrish42 、例は素晴らしいでしょう。
参考までに、scikit-learnには、パイプラインに適合する
このようなものが機能するはずですか?
import pandas as pd
from sklearn.pipeline import TransformerMixin
class DummyEncoder(TransformerMixin):
def __init__(self, columns=None):
self.columns = columns
def transform(self, X, y=None, **kwargs):
return pd.get_dummies(X, columns=self.columns)
def fit(self, X, y=None, **kwargs):
return self
与える
In [15]: df
Out[15]:
A B C
0 1 a a
1 2 b a
In [16]: DummyEncoder().transform(df)
Out[16]:
A B_a B_b C_a
0 1 1 0 1
1 2 0 1 1
列の順序に注意してください。
@TomAugspurger 、実際にはsklearn処理パイプライン自体との互換性は私が興味を持っている部分ではありません。 私が欲しいのは、get_dummes()によって行われた変換をデータセットに保存し、2番目のデータセットに最初のデータセットの値のサブセットがある場合でも、その変換をそのまま適用する(まったく同じ列を作成する)機能です。いくつかのコラムなどで。それは実際に私が「トレイン/テストフレームワークで使用可能」という意味でした。 この説明はより明確ですか? (誰かがまだ必要だと思う例を追加できます。)
sklearnのOneHotEncoder
クラスを知っていますが、他にも制限があります。
@ chrish42と同じ問題に遭遇し、get_dummiesが頭痛の種になっていることに気づきました。
次のdf_trainDataFrameからのデータを処理すると仮定します。
`` `.python
df_train = pandas.DataFrame({"car":["seat"、 "bmw"]、 "color":["red"、 "green"]})
pandas.get_dummies(df_train)
car_bmw car_seat color_green color_red
0 0 1 0 1
1 1 0 1 0
Then we are provided with
``` .python
df_test = pandas.DataFrame({"car":["seat","mercedes"], "color":["red","green"]})
pandas.get_dummies(df_test )
car_mercedes car_seat color_green color_red
0 0 1 0 1
1 1 0 1 0
df_trainで変数「car」の「mercedes」値を観察したことがないので、次の1つのホットエンコーディングを取得できるようにしたいと思います。
`` `.python
car_bmw car_seat color_green color_red
0 0 1 0 1
1 0 0 1 0
Where the column car_mercedes actually never appears.
This could be solved by allowing get_dummies to receive an input dictionary stating the accepted values that we allow for each column.
Returning to the previous example, we could give as input to get_dummies the following dict of sets
``` .python
accepted_values_per_column = {'car': {'bmw', 'seat'}, 'color': {'green', 'red'}}
そして、get_dummiesが戻ることを期待します
`` `.python
get_dummies(df_test、accepted_values_per_column = Accepted_values_per_column)
car_bmw car_seat color_green color_red
0 0 1 0 1
1 0 0 1 0
`` `
そして、get_dummies(df_test)がすでに返しているものを返すことを期待します。
_可能性のある_監視されていない変数を指定する場合は、変数をCategorical
する必要があります。 これは、作成時または作成後に行うことができます。ドキュメントを参照してください
In [5]: df_train = pd.DataFrame({"car":Series(["seat","bmw"]).astype('category',categories=['seat','bmw','mercedes']),"color":["red","green"]})
In [6]: df_train
Out[6]:
car color
0 seat red
1 bmw green
In [7]: pd.get_dummies(df_train )
Out[7]:
car_seat car_bmw car_mercedes color_green color_red
0 1 0 0 0 1
1 0 1 0 1 0
元の質問は明確に指定されていないため、終了します。
また、エンコードからCategoricalに戻るまでの逆の場合は、Categorical.from_codesを使用します。
もう少し一方的なアドバイス。 カテゴリの係数の正確な推定にまったく関心がある場合は、エンコードされた列の1つを削除してください。そうしないと、切片との多重共線性が得られます(ある場合)。
2015年10月5日には、5:34で、ジェフRebackの[email protected]は書きました:
観測されていない可能性のある変数を指定する場合は、変数をカテゴリカルにする必要があります。 これは、作成時または作成後に行うことができます。ドキュメントを参照してください
[5]の場合:df_train = pd.DataFrame({"car":Series(["seat"、 "bmw"])。astype( 'category'、categories = ['seat'、 'bmw'、 'mercedes'] )、 "color":["red"、 "green"]})
[6]の場合:df_train
アウト[6]:
車の色
0シートレッド
1bmwグリーン[7]の場合:pd.get_dummies(df_train)
アウト[7]:
car_seat car_bmw car_mercedes color_green color_red
0 1 0 0 0 1
1 0 1 0 1 0
元の質問は明確に指定されていないため、終了します。—
このメールに直接返信するか、GitHubで表示してください。
@TomAugspurger @jreback私は最近同じ問題に
train_a = pd.DataFrame({"IsBadBuy":[0,1,0]、 "Make":['Toyota'、 'Mazda'、 'BMW']})
IsBadBuy Make_BMW Make_Mazda Make_Toyota
0 0 0 0 1
1 1 0 1 0
2 0 1 0 0
test_a = pd.DataFrame({"Make":['Toyota'、 'BMW']})
print pd.get_dummies(test_a、columns = ['Make'])
Make_BMW Make_Toyota
0 0 1
1 1 0
ここでは、MLアルゴリズムが同じ数の特徴を期待し、テストで取得した値がトレイン内の値のサブセットになるため、Make_Mazda列を保持するのが理想的です。
カテゴリカルを使用します。 これにより、正しい列数に拡張されます。 興味のある方はhttps://m.youtube.com/watch?v=KLPtEBokqQ0
_____________________________
投稿者:アジャイSaxena [email protected]
送信日:2017年1月12日木曜日18:31
件名:Re:[pandas-dev / pandas]ウィッシュリスト:get_dummies()をtrain / testフレームワークで使用できるようにする(#8918)
宛先: pandas -dev /
Cc:Tom Augspurger [email protected] 、言及@ noreply.github.com
@jreback私は最近同じ問題に
train_a = pd.DataFrame({"IsBadBuy":[0,1,0]、 "Make":['Toyota'、 'Mazda'、 'BMW']})
IsBadBuy Make_BMW Make_Mazda Make_Toyota
0 0 0 0 1
1 1 0 1 0
2 0 1 0 0
test_a = pd.DataFrame({"Make":['Toyota'、 'BMW']})
print pd.get_dummies(test_a、columns = ['Make'])
Make_BMW Make_Toyota
0 0 1
1 1 0
ここでは、MLアルゴリズムが同じ数の特徴を期待し、テストで取得した値がトレイン内の値のサブセットになるため、Make_Mazda列を保持するのが理想的です。
—
あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信するか、GitHubで表示するか、スレッドをミュートしてください。
ありがとう@TomAugspurger
@TomAugspurgerによって与えられたPyDataシカゴ2016年の話は本当によくやりました。 彼は、この問題/リクエストを閉じてはならないすべての理由を説明するという素晴らしい仕事をしました。 私見では、彼のクラスDummyEncoderまたはそれに相当するものをPandasに含める必要があります。 はい、私は彼のgithubにアクセスして、彼のクラスをコピー/エミュレートできますが、ライブラリ内でサポートされているだけの方がはるかに便利です。
データモデリングの早い段階で使用できるライブラリが必要だと思います
パイプラインであり、パンダやscikit-learnでうまく機能します。
しかし、パンダはscikit-learnに依存していません。その逆も同様です。 あると思います
両方の上に構築された別のライブラリのための部屋。
6:13 PMでの水、2017年5月10日には、ブライアン・ワイリー[email protected]
書きました:
@TomAugspurgerによるPyDataシカゴ2016トーク
https://github.com/TomAugspurgerは本当によくできていました。 彼はしました
この問題/リクエストが必要なすべての理由を説明する素晴らしい仕事
閉じていません。 私見彼のクラスDummyEncoderまたはいくつかの合理的な
同等のものが適切なパンダに含まれている必要があります。 はい、彼のgithubにアクセスできます
彼のクラスをコピー/エミュレートしますが、それを持っている方がはるかに良いでしょう
ライブラリ内でサポートされています。ところで、 @ TomAugspurgerhttps ://github.com/TomAugspurgerは私のかもしれないと思います
新しいお気に入りのPyDataの第一人者。 私は彼がいるすべてのものを追い詰めるつもりです
完了/作業して、それを吸収しようとします..不気味な/ストーキングな方法ではありません..あなた
まったく気味が悪いことではない通常の方法で知っています。 :)—
あなたが言及されたのであなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/pandas-dev/pandas/issues/8918#issuecomment-300638388 、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/ABQHIpTqgHSE7iFVF9Pp4_YoKB9DPLcEks5r4kSrgaJpZM4DB6Hb
。
ここに私たちの何人かが取り組んだ小さな解決策があります。 フィット/変換機能を備えたダミー変数。
https://github.com/joeddav/get_smarties
フィードバックと貢献が役に立ちます!
これは#14017に関連しているようです
私はこの問題に正確に役立つかもしれない解決策を作成しました。 トレインテストフレームワークの1つのホットエンコーディングカテゴリ変数。 また、データセットが大きすぎてマシンのメモリに収まらない場合も処理できます。
https://github.com/yashu-seth/dummyPy
これに関する小さなチュートリアルもここにあります。
これを購読している人はdask-mlの実装に興味があるかもしれません
@TomAugspurgerこのコードは機能しません。 本番の単一レコードデータを変換しようとすると、存在する単一の値に対して1つのホットエンコードされた列しか表示されません。
何が足りないのですか?
pyodbcをインポートする
ピクルスをインポート
sklearn.linear_modelからimportLogisticRegression
sklearn.linear_modelからimportLinearRegression
numpyをnpとしてインポート
パンダをpdとしてインポートする
sklearn.pipelineからインポートTransformerMixin
sklearn.pipelineからimportmake_pipeline
クラスDummyEncoder(TransformerMixin):
def fit(self、X、y = None):
self.index_ = X.index
self.columns_ = X.columns
self.cat_columns_ = X.select_dtypes(include = ['category'])。columns
self.non_cat_columns_ = X.columns.drop(self.cat_columns_)
self.cat_map_ = {col: X[col].cat for col in self.cat_columns_}
left = len(self.non_cat_columns_)
self.cat_blocks_ = {}
for col in self.cat_columns_:
right = left + len(X[col].cat.categories)
self.cat_blocks_[col], left = slice(left, right), right
return self
def transform(self, X, y=None):
return np.asarray(pd.get_dummies(X))
def inverse_transform(self, X):
non_cat = pd.DataFrame(X[:, :len(self.non_Cat_columns_)],
columns=self.non_cat_columns_)
cats = []
for col, cat in self.cat_map_.items():
slice_ = self.cat_blocks_[col]
codes = X[:, slice_].argmax(1)
series = pd.Series(pd.Categorical.from_codes(
codes, cat.categories, ordered=cat.ordered
), name=col)
cats.append(series)
df = pd.concat([non_cat] + cats, axis=1)[self.columns_]
return df
cnxn = pyodbc.connect( 'DRIVER = {SQL Server}; SERVER = {XXXXX}; DATABASE = {ML_Learn_Taxi}; UID = {XXXX}; PWD = {XXXX}')
sql = "" "
SELECT top 1 CONVERT(int、[order_key])order_key
、CONVERT(int、[service_date_key])service_date_key
、[order_source_desc]
、1 as'return_flag '
FROM [ML_Return_Customer]。[dbo]。[return_customers_test_set]
WHERE [order_source_desc] = 'オンライン'
連合
SELECT top 2 CONVERT(int、[order_key])
、CONVERT(int、[service_date_key])
、[order_source_desc]
、2
FROM [ML_Return_Customer]。[dbo]。[return_customers_test_set]
WHERE [order_source_desc] = 'インバウンドコール'
連合
SELECT top 1 CONVERT(int、[order_key])
、CONVERT(int、[service_date_key])
、[order_source_desc]
、1
FROM [ML_Return_Customer]。[dbo]。[return_customers_test_set]
WHERE [order_source_desc] = 'アウトバウンドコール'
"" "
prod_sql = "" "
SELECT top 1 CONVERT(int、[order_key])order_key
、CONVERT(int、[service_date_key])service_date_key
、[order_source_desc]
、1 as'return_flag '
FROM [ML_Return_Customer]。[dbo]。[return_customers_test_set]
WHERE [order_source_desc] = 'オンライン'
"" "
InputDataSet = pd.read_sql(sql、cnxn)
ProdDataSet = pd.read_sql(prod_sql、cnxn)
印刷(」* * * *データ
* * * * * ")print( " *カテゴリ列情報
* * ")InputDataSet.info()
print( " *線形回帰
* * ")X = InputDataSet.drop( 'return_flag'、axis = 1)
y = InputDataSet ['return_flag']
A = ProdDataSet.drop( 'return_flag'、axis = 1)
B = ProdDataSet ['return_flag']
enc = DummyEncoder()
enc.fit(X)
Prod = enc.transform(A)
印刷(製品)
OUTPUT:* * * *データ
* * * *したがって、このスレッドは少し厄介だと思うので、ここで簡単な解決策と、これがすでに可能である方法を要約しようと思います。 1つのコラムで説明しますが、多くのコラムに一般化することができます。
したがって、「適合」呼び出しでは、次のようにします。
categories = sorted(training_data.iloc[:, column_index].value_counts(dropna=True).index)
categories
を、フィッティング中に学習している状態に格納します。
そして、「変換」では、次のことを行います。
from pandas.api import types as pandas_types
categorical_data = testing_data.iloc[:, [column_index]].astype(
pandas_types.CategoricalDtype(categories=categories),
)
one_hot_encoded = pandas.get_dummies(categorical_data)
また、値の同じマッピングで常にワンホットエンコーディングを実行します。 トレーニング中に何らかのカテゴリ値が存在しなかった場合、テスト中にはNaNと見なされます。 テスト中に何らかの値が表示されない場合、その値には列が設定されません。
それはとてもいいです。 これをやりたいと思っているすべての人が、新たに発見する必要がないことを願っています。 ;-)
KaggleXGBoostチュートリアルの演習で以下のコードを見ました。 これでうまくいきます。
X_train = pd.get_dummies(X_train)
X_valid = pd.get_dummies(X_valid)
X_test = pd.get_dummies(X_test)
X_train, X_valid = X_train.align(X_valid, join='left', axis=1)
X_train, X_test = X_train.align(X_test, join='left', axis=1)
私も同じ問題に何度も直面しました。 私は物事を簡単にするクラスを以下に書きました(この議論からアイデアを取り入れます)。
import pandas
from sklearn.preprocessing import LabelEncoder
class CategoryEncoder:
'''
labelEncoding : boolean -> True If the categorical columns are to be label encoded
oneHotEncoding : boolean -> True If the categorical columns are to be one hot encoded (using pandas.get_dummies method)
dropFirst : boolean -> True if first column is to be dropped (usually to avoid multi-collinearity) post one hot encoding
Doesn't matter if oneHotEncoding = False
df : pandas.DataFrame() -> dataframe object that needs to be encoded
catCols : list -> list of the categorical columns that need to be encoded
'''
def __init__(self,labelEncoding=True,oneHotEncoding=False,dropFirst=False):
self.labelEncoding = labelEncoding
self.oneHotEncoding = oneHotEncoding
self.dropFirst = dropFirst
self.labelEncoder = {}
self.oneHotEncoder = {}
def fit(self,df,catCols=[]):
df1 = df.copy()
if self.labelEncoding:
for col in catCols:
labelEncoder = LabelEncoder()
labelEncoder.fit(df1.loc[:,col].astype(str))
df1.loc[:,col] = labelEncoder.transform(df1.loc[:,col])
self.labelEncoder[col] = labelEncoder.classes_
if self.oneHotEncoding:
for col in catCols:
cats = sorted(df1.loc[:,col].value_counts(dropna=True).index)
self.oneHotEncoder[col] = cats
def transform(self,df,catCols=[]):
df1 = df.copy()
if self.labelEncoding:
for col in catCols:
labelEncoder = self.labelEncoder[col]
labelEncoder = {v:i for i,v in enumerate(labelEncoder.tolist())}
print(labelEncoder)
df1.loc[:,col] = df1.loc[:,col].map(labelEncoder)
if self.oneHotEncoding:
for col in catCols:
oneHotEncoder = self.oneHotEncoder[col]
df1.loc[:,col] = df1.loc[:,col].astype(pandas.CategoricalDtype(categories=oneHotEncoder))
df1 = pandas.get_dummies(df1,columns=catCols,drop_first=self.dropFirst)
return df1
エンコーダーのインスタンスの開始と使用も簡単です。
enc1 = CategoryEncoder(True,False) # Will label encode but not one-hot encode
enc2 = CategoryEncoder(False,True,True) # Will one-hot encode but not label encode
enc3 = CategoryEncoder(True,True,True) # Will label encode first and then one-hot encode
# List of categorical columns you want to encode
categorical_columns = ['col_1', 'col_2']
enc1.fit(train_df, categorical_columns)
enc1.transform(test_df, categorical_columns) # Returns the dataframe encoded columns
注:これは、データフレームで使用できない列名を渡すなどの例外を処理しません。
最も参考になるコメント
_可能性のある_監視されていない変数を指定する場合は、変数を
Categorical
する必要があります。 これは、作成時または作成後に行うことができます。ドキュメントを参照してください元の質問は明確に指定されていないため、終了します。