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).
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.
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 hijauDalam [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 .
Orang yang berlangganan ini mungkin tertarik dengan penerapan dask-ml
@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
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
* * * * * ")print (" * Info Kolom 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)
Prod = enc.transform (A)
cetak (Prod)
OUTPUT: * * * * Data
* * * *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
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 dokumenPertanyaan asli tidak ditentukan dengan baik, jadi penutup.