Get_dummies (Pandalar) ve OneHotEncoder (Scikit-learn) arasındaki artılar ve eksiler nelerdir?


92

Makine öğrenimi sınıflandırıcıları için kategorik değişkenleri sayısal hale dönüştürmek için farklı yöntemler öğreniyorum. pd.get_dummiesYönteme rastladım ve sklearn.preprocessing.OneHotEncoder()performans ve kullanım açısından nasıl farklı olduklarını görmek istedim.

Ben nasıl kullanılacağı hakkında bir öğretici buldum OneHotEncoder()üzerinde https://xgdgsc.wordpress.com/2015/03/20/note-on-using-onehotencoder-in-scikit-learn-to-work-on-categorical-features/ beri sklearndokümantasyon Bu özellikle ilgili çok yararlı değildi. Doğru yapmadığımı hissediyorum ... ama

Bazı kullanmanın avantajlarını ve dezavantajlarını açıklayabilir pd.dummiesüzerinde sklearn.preprocessing.OneHotEncoder()ve tersi? Bunun OneHotEncoder()size seyrek bir matris verdiğini biliyorum, ancak bunun dışında nasıl kullanıldığından ve pandasyönteme göre faydalarının ne olduğundan emin değilim . Verimsiz mi kullanıyorum?

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
sns.set()

%matplotlib inline

#Iris Plot
iris = load_iris()
n_samples, m_features = iris.data.shape

#Load Data
X, y = iris.data, iris.target
D_target_dummy = dict(zip(np.arange(iris.target_names.shape[0]), iris.target_names))

DF_data = pd.DataFrame(X,columns=iris.feature_names)
DF_data["target"] = pd.Series(y).map(D_target_dummy)
#sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)  \
#0                  5.1               3.5                1.4               0.2   
#1                  4.9               3.0                1.4               0.2   
#2                  4.7               3.2                1.3               0.2   
#3                  4.6               3.1                1.5               0.2   
#4                  5.0               3.6                1.4               0.2   
#5                  5.4               3.9                1.7               0.4   

DF_dummies = pd.get_dummies(DF_data["target"])
#setosa  versicolor  virginica
#0         1           0          0
#1         1           0          0
#2         1           0          0
#3         1           0          0
#4         1           0          0
#5         1           0          0

from sklearn.preprocessing import OneHotEncoder, LabelEncoder
def f1(DF_data):
    Enc_ohe, Enc_label = OneHotEncoder(), LabelEncoder()
    DF_data["Dummies"] = Enc_label.fit_transform(DF_data["target"])
    DF_dummies2 = pd.DataFrame(Enc_ohe.fit_transform(DF_data[["Dummies"]]).todense(), columns = Enc_label.classes_)
    return(DF_dummies2)

%timeit pd.get_dummies(DF_data["target"])
#1000 loops, best of 3: 777 µs per loop

%timeit f1(DF_data)
#100 loops, best of 3: 2.91 ms per loop

Yanıtlar:


57

OneHotEncoderdize değerlerini doğrudan işleyemez. Nominal özellikleriniz dizelerden ibaretse, önce bunları tamsayılarla eşlemeniz gerekir.

pandas.get_dummiestam tersi. Varsayılan olarak, sütunlar belirtilmediği sürece yalnızca dize sütunlarını tek sıcak gösterime dönüştürür.


Hey @nos, bu yanıtla ilgili size geri dönmemizde geciktiğim için özür dilerim
O.rka

1
Bunun dışında biri diğerine göre verimli mi?
Ankit Seth

6
güncellemesi, OneHotEncoder0.20.0 sürümünde dizilere de uygulanamaz.
Bs O

15
@BsHe artık sklearn 0.20.3'te doğru değil: OneHotEncoder(sparse=False).fit_transform(pd.DataFrame(pd.Series(['good','bad','worst','good', 'good', 'bad'])))çalışır, bu da OneHotEncoderstirngs üzerinde uygulanabileceği anlamına gelir .
dzieciou

1
Yeni görünmeyen verileri ile kodlayamazsınız pd.get_dummies.
2020

140

Makine öğrenimi için neredeyse kesinlikle kullanmak istersiniz sklearn.OneHotEncoder. Basit analizler gibi diğer görevler için pd.get_dummies, biraz daha uygun olanı kullanabilirsiniz .

Bunun sklearn.OneHotEncoderen son sürümde güncellendiğini ve böylece tamsayıların yanı sıra kategorik değişkenler için dizeleri kabul ettiğini unutmayın .

İşin özü, sklearnkodlayıcının devam eden ve daha sonra tutarlı sonuçlarla aynı kategorik değişkenleri kullanan yeni veri setlerine uygulanabilen bir işlev yaratmasıdır .

from sklearn.preprocessing import OneHotEncoder

# Create the encoder.
encoder = OneHotEncoder(handle_unknown="ignore")
encoder.fit(X_train)    # Assume for simplicity all features are categorical.

# Apply the encoder.
X_train = encoder.transform(X_train)
X_test = encoder.transform(X_test)

Oluşturduğumuz aynı kodlayıcıyı X_trainyeni veri setine nasıl uyguladığımıza dikkat edin X_test.

Değişkenlerinden birinden X_testfarklı seviyeler içeriyorsa ne olacağını düşünün X_train. Örneğin, diyelim ki X_train["color"]sadece "red"ve içerir "green", ancak bunlara ek olarak X_test["color"]bazen içerir "blue".

Kullanırsak pd.get_dummies, X_testsahip olmayan ek bir "color_blue"sütun ile sonuçlanır X_trainve tutarsızlık muhtemelen daha sonra kodumuzu kırar, özellikle de eğitim aldığımız X_testbir sklearnmodeli besliyorsak X_train.

Ve bir seferde tek bir örnek aldığımız üretimde bu gibi verileri işlemek istiyorsak, pd.get_dummiesişe yaramayacaktır.

İle sklearn.OneHotEncoderbiz kodlayıcı oluşturduktan sonra diğer taraftan, sadece için sütunlar, aynı çıktılı her zaman üretmek için yeniden kullanabilirsiniz "red"ve "green". Ve yeni seviyeyle karşılaştığında ne olacağını açıkça kontrol edebiliriz "blue": bunun imkansız olduğunu düşünürsek, ona bir hata atmasını söyleyebiliriz handle_unknown="error"; aksi takdirde devam etmesini söyleyebiliriz ve sadece kırmızı ve yeşil sütunları 0'a ayarlayabiliriz handle_unknown="ignore".


23
Bu cevabın kabul edilenden çok daha büyük bir etkiye sahip olduğuna inanıyorum. Gerçek sihir, üretimde ortaya çıkması gereken bilinmeyen kategorik özellikleri ele almaktır.
barker

2
Bunun kabul edilen cevaptan daha iyi, daha eksiksiz bir cevap olduğunu düşünüyorum.
Chiraz BenAbdelkader

1
Evet. IMHO, bu kabul edilen cevaptan daha iyi bir cevap.
dami.max

1
Evet . Bu cevap kesinlikle one_hot_encoder daha iyi bir net örnek ile birlikte olabileceğini niçin daha iyi açıklıyor
Binod Mathews

1
Bu güzel bir açıklamaydı.
Tebrikler

4

neden sütunları sonuçta elde edilen get_dummies'den col_list değişken olarak önbelleğe alıp kaydetmiyorsunuz ve ardından treni test veri kümelerine göre hizalamak için pd.reindex'i kullanmıyorsunuz .... örnek:

df = pd.get_dummies(data)
col_list = df.columns.tolist()

new_df = pd.get_dummies(new_data)
new_df = new_df.reindex(columns=col_list).fillna(0.00) 

Bu soruya nasıl cevap veriyor?
jorijnsmit

Sklearn OHE'nin handle_unknown nedeniyle daha üstün olduğuna dair önceki yorumu çürütmek için daha fazlası. Aynı şey pandaların reindex'i kullanılarak da gerçekleştirilebilir.
Carl

Get_dummies kullanımıyla ilgili tek seferlik çalışma dışında sinsi bir sorun olabilir. Drop_first = True'ya sahipseniz ve sonraki örnek, düşürülen değeri içermiyorsa ne olur?
Darphane

3

Carl'ın cevabını gerçekten beğendim ve ona olumlu oy verdim. Carl'ın örneğini biraz genişleteceğim, böylece daha fazla insan pd.get_dummies'in bilinmeyenlerin üstesinden gelebileceğini umarım. Aşağıdaki iki örnek, pd.get_dummies'in OHE ile bilinmeyeni ele alırken aynı şeyi başarabileceğini göstermektedir.

# data is from @dzieciou's comment above
>>> data =pd.DataFrame(pd.Series(['good','bad','worst','good', 'good', 'bad']))
# new_data has two values that data does not have. 
>>> new_data= pd.DataFrame(
pd.Series(['good','bad','worst','good', 'good', 'bad','excellent', 'perfect']))

Pd.get_dummies kullanma

>>> df = pd.get_dummies(data)
>>> col_list = df.columns.tolist()
>>> print(df)
   0_bad  0_good  0_worst
0      0       1        0
1      1       0        0
2      0       0        1
3      0       1        0
4      0       1        0
5      1       0        0
6      0       0        0
7      0       0        0

>>> new_df = pd.get_dummies(new_data)
# handle unknow by using .reindex and .fillna()
>>> new_df = new_df.reindex(columns=col_list).fillna(0.00)
>>> print(new_df)
#    0_bad  0_good  0_worst
# 0      0       1        0
# 1      1       0        0
# 2      0       0        1
# 3      0       1        0
# 4      0       1        0
# 5      1       0        0
# 6      0       0        0
# 7      0       0        0

OneHotEncoder'ı kullanma

>>> encoder = OneHotEncoder(handle_unknown="ignore", sparse=False)
>>> encoder.fit(data)
>>> encoder.transform(new_data)
# array([[0., 1., 0.],
#        [1., 0., 0.],
#        [0., 0., 1.],
#        [0., 1., 0.],
#        [0., 1., 0.],
#        [1., 0., 0.],
#        [0., 0., 0.],
#        [0., 0., 0.]])

Lütfen cevabınızı drop_first = True ile bir örnek içerecek şekilde genişletin ve ardından bırakılan değeri içermeyen yeni verileri de gösterin.
Darphane
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.