Pandas: ウィッシュリスト:get_dummies()をトレイン/テストフレームワークで使用できるようにする

作成日 2014年11月28日  ·  21コメント  ·  ソース: pandas-dev/pandas

Pandasにget_dummies()があるのは本当に素晴らしいですが、機械学習に役立つためには、train / testフレームワーク(またはsklearnの用語では「fit_transform」と「transform」)で使用できる必要があります。 さらに説明が必要な場合はお知らせください。

だから、これはパンダにその機能を追加するためのウィッシュリストのバグレポートだと思います。 プルリクエストを作成することもできます。これがパンダで役立つものであることに人々が同意した場合(そして、このプロジェクトへの私の最初の貢献となるものについて少し指導し、コードレビューを行う用意があります)。

Categorical Reshaping Usage Question

最も参考になるコメント

_可能性のある_監視されていない変数を指定する場合は、変数を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

元の質問は明確に指定されていないため、終了します。

全てのコメント21件

サンプルフレームからの入力と出力を使用した擬似コードの例はどうでしょうか。

@ 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が頭痛の種になっていることに気づきました。

現在のgetダミーの制限の例

次の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

これに関する小さなチュートリアルもここにあります

@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

SQLからパンダデータフレームにデータをインポートする

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)

print( " *カテゴリ列情報

* * ")
列= ['order_source_desc']
InputDataSet [columns] = InputDataSet [columns] .apply(lambda x:x.astype( 'category'))

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)

雨= enc.transform(X)

Prod = enc.transform(A)

印刷(製品)

OUTPUT:* * * *データ

* * * *
order_key service_date_key order_source_desc return_flag
0 1008793720151214オンライン1
1 1008817420151201インバウンドコール2
2 1008855320151217インバウンドコール2
3 66347820160806アウトバウンドコール1
*カテゴリー表形式情報* *

RangeIndex:4エントリ、0〜3
データ列(合計4列):
order_key4非nullint64
service_date_key4非nullint64
order_source_desc4非nullカテゴリ
return_flag 4 null以外のint64
dtypes:category(1)、int64(3)
メモリ使用量:284.0バイト
*線形回帰* * *
[[10087937 20151214 1]]

したがって、このスレッドは少し厄介だと思うので、ここで簡単な解決策と、これがすでに可能である方法を要約しようと思います。 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

注:これは、データフレームで使用できない列名を渡すなどの例外を処理しません。

このページは役に立ちましたか?
0 / 5 - 0 評価
bleepcoder.com は、世界中の開発者にソリューションを提供するために、公にライセンスされた GitHub の情報を使用しています。弊社は、GitHub, Inc.をはじめ、GitHubを利用した開発者のプロジェクトとは提携しておりません。私たちは、私たちのサーバー上のビデオや画像をホストしていません。すべての権利はそれぞれの所有者に帰属します。
このページのソース: ソース

人気のあるプログラミング言語
GitHub の人気プロジェクト
その他の GitHub プロジェクト

© 2024 bleepcoder.com - Contact
Made with in the Dominican Republic.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.