Pandas: Wishlist: buat get_dummies () bisa digunakan untuk train / test framework

Dibuat pada 28 Nov 2014  ·  21Komentar  ·  Sumber: pandas-dev/pandas

Memiliki get_dummies () di Pandas benar-benar bagus, tetapi agar berguna untuk pembelajaran mesin, itu perlu digunakan dalam kerangka kerja pelatihan / pengujian (atau "fit_transform" dan "transform", dengan terminologi sklearn). Beri tahu saya jika perlu penjelasan lebih lanjut.

Jadi, saya kira ini adalah laporan bug daftar keinginan untuk menambahkan fungsionalitas itu ke Pandas. Saya bahkan dapat membuat permintaan tarik, jika orang setuju ini akan menjadi sesuatu yang berguna untuk dimiliki di Pandas (dan bersedia untuk melatih sedikit dan melakukan tinjauan kode untuk apa yang akan menjadi kontribusi pertama saya untuk proyek ini).

Categorical Reshaping Usage Question

Komentar yang paling membantu

Anda hanya perlu membuat variabel Anda Categorical jika Anda ingin menentukan variabel tak teramati _possibly_. Ini dapat dilakukan pada waktu pembuatan atau setelahnya, lihat dokumen

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

Pertanyaan asli tidak ditentukan dengan baik, jadi penutup.

Semua 21 komentar

nah bagaimana dengan contoh kode semu dengan input dan output dari bingkai sampel akan berguna

@ chrish42 , contoh akan sangat bagus.

FYI scikit-learn memiliki kelas OneHotEncoder yang cocok dengan pipeline mereka.

Sesuatu seperti ini seharusnya bekerja?

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

Memberi

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

Hati-hati dengan urutan kolom.

@TomAugspurger , sebenarnya kompatibilitas dengan pipeline pemrosesan sklearn itu sendiri bukanlah bagian yang menarik minat saya. Yang saya inginkan adalah kemampuan untuk menyimpan transformasi yang dilakukan oleh get_dummes () ke dataset, dan kemudian menerapkan transformasi tersebut sebagaimana adanya (membuat kolom yang sama persis), bahkan jika dataset kedua memiliki subset dari nilai yang pertama di beberapa kolom, dll. Itulah yang sebenarnya saya maksud dengan "dapat digunakan dalam kerangka kerja kereta / pengujian". Apakah penjelasan ini lebih jelas? (Saya dapat menambahkan contoh yang menurut seseorang masih dibutuhkan.)

Saya mengetahui kelas OneHotEncoder di sklearn, tetapi memiliki batasan lain.

Saya tersandung masalah yang sama seperti @ chrish42 dan saya menemukan get_dummies membuat saya pusing.

Contoh batasan arus get dummies

Mari kita asumsikan kita bekerja dengan data dari df_train DataFrame berikut

".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

Karena saya tidak pernah mengamati nilai "mercedes" untuk variabel "car" di df_train, saya ingin mendapatkan encoding panas berikut:

".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'}}

dan kami mengharapkan get_dummies untuk kembali

".python
get_dummies (df_test, accept_values_per_column = accept_values_per_column)

       car_bmw  car_seat  color_green  color_red

0 0 1 0 1
1 0 0 1 0
``

dan mengharapkan get_dummies (df_test) mengembalikan apa yang sudah dikembalikan.

Anda hanya perlu membuat variabel Anda Categorical jika Anda ingin menentukan variabel tak teramati _possibly_. Ini dapat dilakukan pada waktu pembuatan atau setelahnya, lihat dokumen

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

Pertanyaan asli tidak ditentukan dengan baik, jadi penutup.

Dan ketika Anda pergi ke arah lain, dari encoding ke kembali ke Categorical Anda akan menggunakan Categorical.from_codes.

Satu lagi nasihat yang tidak diminta. Jika Anda benar-benar peduli tentang perkiraan akurat koefisien pada kategorikal, jatuhkan salah satu kolom yang dikodekan atau Anda akan memiliki multikolinieritas dengan intersep (jika Anda memilikinya).

Pada 5 Oktober 2015, pukul 05:34, Jeff Reback [email protected] menulis:

Anda hanya perlu membuat variabel Anda Kategorikal jika Anda ingin menentukan variabel yang mungkin tidak teramati. Ini dapat dilakukan pada waktu pembuatan atau setelahnya, lihat dokumen

Dalam [5]: df_train = pd.DataFrame ({"car": Series (["seat", "bmw"]). Astype ('category', categories = ['seat', 'bmw', 'mercedes'] ), "color": ["red", "green"]})

Dalam [6]: df_train
Keluar [6]:
warna mobil
0 kursi merah
1 bmw hijau

Dalam [7]: pd.get_dummies (df_train)
Keluar [7]:
car_seat car_bmw car_mercedes color_green color_red
0 1 0 0 0 1
1 0 1 0 1 0
Pertanyaan asli tidak ditentukan dengan baik, jadi penutup.

-
Balas email ini secara langsung atau lihat di GitHub.

@TomAugspurger @jreback Saya rasa saya mengalami masalah yang sama belakangan ini dan saya ingin memberikan contoh

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, kolom = ['Make'])

Make_BMW Make_Toyota
0 0 1
1 1 0

Di sini, idealnya kolom Make_Mazda harus dipertahankan karena algoritme ML mengharapkan jumlah fitur yang sama dan nilai yang kita dapatkan dalam pengujian akan menjadi bagian dari yang dilatih.

Gunakan Categorical. Itu akan meluas ke jumlah kolom yang benar. Saya memberikan ceramah tentang ini jika Anda tertarik https://m.youtube.com/watch?v=KLPtEBokqQ0

    _____________________________

Dari: Ajay Saxena [email protected]
Dikirim: Kamis, 12 Januari 2017 18:31
Subject: Re: [pandas-dev / pandas] Wishlist: buat get_dummies () dapat digunakan untuk kerangka kerja pelatihan / pengujian (# 8918)
Kepada: pandas-dev / pandas [email protected]
Cc: Tom Augspurger [email protected] , Sebutkan [email protected]

@jreback Saya rasa saya telah mengalami masalah yang sama akhir-akhir ini dan saya ingin memberikan contoh

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, kolom = ['Make'])

Make_BMW Make_Toyota
0 0 1
1 1 0

Di sini, idealnya kolom Make_Mazda harus dipertahankan karena algoritme ML mengharapkan jumlah fitur yang sama dan nilai yang kita dapatkan dalam pengujian akan menjadi bagian dari yang dilatih.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub, atau nonaktifkan utasnya.

Terima kasih @TomAugspurger

Ceramah PyData Chicago 2016 yang diberikan oleh @TomAugspurger dilakukan dengan sangat baik. Dia melakukan pekerjaan yang luar biasa dalam menggambarkan semua alasan mengapa masalah / permintaan ini tidak boleh ditutup. IMHO baik kelasnya DummyEncoder atau sejenisnya yang wajar harus dimasukkan ke dalam Panda dengan benar. Ya, saya bisa pergi ke githubnya dan menyalin / meniru kelasnya tetapi akan jauh lebih baik jika hanya didukung di dalam perpustakaan.

Saya pikir ada kebutuhan akan perpustakaan yang berjalan lebih awal dalam pemodelan data
pipeline dan bekerja dengan baik dengan panda dan scikit-learn.
Tetapi panda tidak bergantung pada scikit-learn dan sebaliknya. Saya pikir ada
ruangan untuk perpustakaan lain yang dibangun di atas keduanya.

Pada Rabu, 10 Mei 2017 pukul 18.13, Brian Wylie [email protected]
menulis:

Ceramah PyData Chicago 2016 yang diberikan oleh @TomAugspurger
https://github.com/TomAugspurger dilakukan dengan sangat baik. Dia melakukan a
pekerjaan yang luar biasa dalam menggambarkan semua alasan mengapa masalah / permintaan ini harus
tidak ditutup. IMHO baik kelasnya DummyEncoder atau yang masuk akal
padanan harus disertakan dalam Panda. Ya saya bisa pergi ke github nya
dan menyalin / meniru kelasnya tetapi akan jauh lebih baik jika memilikinya
didukung di dalam perpustakaan.

BTW Saya pikir @TomAugspurger https://github.com/TomAugspurger mungkin milik saya
guru PyData favorit baru. Aku akan memburu semua yang dia punya
selesai / mengerjakan dan mencoba untuk menyerapnya .. tidak dengan cara yang menyeramkan / mengintai .. Anda
tahu hanya dengan cara biasa yang tidak menyeramkan sama sekali. :)

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/pandas-dev/pandas/issues/8918#issuecomment-300638388 ,
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/ABQHIpTqgHSE7iFVF9Pp4_YoKB9DPLcEks5r4kSrgaJpZM4DB6Hb
.

Berikut adalah sedikit solusi yang beberapa dari kami kerjakan yang mungkin berguna untuk beberapa di sini. Variabel tiruan dengan kemampuan fit / transform.

https://github.com/joeddav/get_smarties

Umpan balik dan kontribusi akan sangat membantu!

Ini tampaknya terkait dengan # 14017

Saya telah membuat solusi yang mungkin bisa membantu dalam masalah ini. Satu variabel kategori Hot Encoding dalam kerangka kerja pengujian kereta. Itu juga dapat menangani kasus ketika kumpulan data terlalu besar untuk muat dalam memori mesin.

https://github.com/yashu-seth/dummyPy

Anda juga dapat menemukan tutorial kecil tentang ini di sini .

@TomAugspurger Kode ini tidak bekerja. Ketika saya pergi untuk mengubah data rekaman tunggal produksi saya itu hanya memberi saya satu kolom yang dikodekan panas untuk nilai tunggal yang ada.
Apa yang saya lewatkan?

impor pyodbc
impor acar
dari sklearn.linear_model import LogisticRegression
dari sklearn.linear_model import LinearRegression

impor numpy sebagai np
impor panda sebagai pd
dari sklearn.pipeline impor TransformerMixin
dari sklearn.pipeline impor make_pipeline

kelas DummyEncoder (TransformerMixin):
def fit (self, X, y = None):
self.index_ = X.index
self.columns_ = X.columns
self.cat_columns_ = X.select_dtypes (sertakan = ['category']). kolom
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

mengimpor data dari SQL ke pandas Dataframe

cnxn = pyodbc.connect ('DRIVER = {SQL Server}; SERVER = {XXXXX}; DATABASE = {ML_Learn_Taxi}; UID = {XXXX}; PWD = {XXXX}')
sql = "" "
PILIH 1 CONVERT teratas (int, [order_key]) order_key
, CONVERT (int, [service_date_key]) service_date_key
, [order_source_desc]
, 1 sebagai 'return_flag'
DARI [ML_Return_Customer]. [Dbo]. [Return_customers_test_set]
DI MANA [order_source_desc] = 'Online'
PERSATUAN
PILIH 2 CONVERT teratas (int, [order_key])
, CONVERT (int, [service_date_key])
, [order_source_desc]
, 2
DARI [ML_Return_Customer]. [Dbo]. [Return_customers_test_set]
WHERE [order_source_desc] = 'Panggilan Masuk'
PERSATUAN
PILIH 1 CONVERT teratas (int, [order_key])
, CONVERT (int, [service_date_key])
, [order_source_desc]
, 1
DARI [ML_Return_Customer]. [Dbo]. [Return_customers_test_set]
WHERE [order_source_desc] = 'Panggilan Keluar'
"" "

prod_sql = "" "
PILIH 1 CONVERT teratas (int, [order_key]) order_key
, CONVERT (int, [service_date_key]) service_date_key
, [order_source_desc]
, 1 sebagai 'return_flag'
DARI [ML_Return_Customer]. [Dbo]. [Return_customers_test_set]
DI MANA [order_source_desc] = 'Online'
"" "

InputDataSet = pd.read_sql (sql, cnxn)
ProdDataSet = pd.read_sql (prod_sql, cnxn)

print (" * * * * Data

* * * * * ")
cetak (InputDataSet)

print (" * Info Kolom Kategori

* * ")
kolom = ['order_source_desc']
InputDataSet [kolom] = InputDataSet [kolom] .apply (lambda x: x.astype ('kategori'))

InputDataSet.info ()

print (" * Regresi Linear

* * ")

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)

hujan = enc.transform (X)

Prod = enc.transform (A)

cetak (Prod)

OUTPUT: * * * * Data

* * * *
order_key service_date_key order_source_desc return_flag
0 10087937 20151214 Online 1
1 10088174 20151201 Panggilan Masuk 2
2 10088553 20151217 Panggilan Masuk 2
3 663478 20160806 Panggilan Keluar 1
* Info Kolom Kategori * *

RangeIndex: 4 entri, 0 hingga 3
Kolom data (total 4 kolom):
order_key 4 non-null int64
service_date_key 4 non-null int64
order_source_desc 4 kategori bukan nol
return_flag 4 non-null int64
dtypes: kategori (1), int64 (3)
penggunaan memori: 284.0 byte
* Regresi Linier * * *
[[10087937 20151214 1]]

Jadi menurut saya utas ini agak berantakan, jadi saya akan mencoba merangkum solusi sederhana di sini dan bagaimana ini sudah mungkin. Saya akan menunjukkan pada satu kolom, tetapi Anda dapat menggeneralisasikannya ke banyak kolom.

Jadi dalam panggilan "fit" Anda cukup melakukan:

categories = sorted(training_data.iloc[:, column_index].value_counts(dropna=True).index)

Anda menyimpan categories ke kondisi yang Anda pelajari selama pemasangan.

Dan kemudian dalam "mengubah" Anda melakukan:

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)

Dan itu akan melakukan encoding one-hot selalu dalam pemetaan yang sama untuk nilai. Jika beberapa nilai kategorikal tidak ada selama pelatihan, itu akan dilihat sebagai NaN selama pengujian. Jika beberapa nilai tidak terlihat selama pengujian, tidak ada kolom yang akan disetel untuknya.

Bagus sekali. Saya hanya berharap setiap orang yang ingin melakukan ini tidak perlu menemukannya lagi. ;-)

Pendekatan yang disarankan oleh @mitar adalah contoh singkat yang bagus. Untuk eksplorasi lebih lanjut tentang masalah ini, berikut adalah buku catatan yang mungkin berguna / membantu: https://nbviewer.jupyter.org/github/SuperCowPowers/scp-labs/blob/master/notebooks/Categorical_Encoding_Dangers.ipynb

Lihat kode di bawah ini dalam latihan tutorial Kaggle XGBoost. Ini berhasil.

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)

Saya juga menghadapi masalah yang sama beberapa kali. Saya telah menulis sebuah kelas (mengambil ide dari diskusi ini) di bawah ini yang membuat segalanya lebih mudah bagi saya.

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

Mudah untuk memulai dan menggunakan instance encoder juga.

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

CATATAN: Ini tidak akan menangani pengecualian apa pun, mis. Meneruskan nama kolom yang tidak tersedia di dataframe

Apakah halaman ini membantu?
0 / 5 - 0 peringkat
bleepcoder.com menggunakan informasi GitHub berlisensi publik untuk menyediakan solusi bagi pengembang di seluruh dunia untuk masalah mereka. Kami tidak berafiliasi dengan GitHub, Inc. atau dengan pengembang mana pun yang menggunakan GitHub untuk proyek mereka. Kami tidak meng-host video atau gambar apa pun di server kami. Semua hak milik masing-masing pemiliknya.
Sumber untuk halaman ini: Sumber

Bahasa pemrograman populer
Lebih banyak proyek 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.