Saya mencoba menggunakan scikit-learn's LabelEncoder
untuk menyandikan panda DataFrame
label string. Karena kerangka data memiliki banyak (50+) kolom, saya ingin menghindari membuat LabelEncoder
objek untuk setiap kolom; Saya lebih suka hanya memiliki satu LabelEncoder
objek besar yang berfungsi di semua kolom data saya.
Melempar keseluruhan DataFrame
ke dalam LabelEncoder
menciptakan kesalahan di bawah ini. Harap diingat bahwa saya menggunakan data dummy di sini; sebenarnya saya sedang berurusan dengan sekitar 50 kolom data berlabel string, jadi perlu solusi yang tidak merujuk kolom apa pun dengan nama.
import pandas
from sklearn import preprocessing
df = pandas.DataFrame({
'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'],
'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
'New_York']
})
le = preprocessing.LabelEncoder()
le.fit(df)
Traceback (panggilan terakhir terakhir): File "", line 1, dalam File "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py", baris 103, sesuai dengan Anda = column_or_1d (y, warn = True) File "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py", baris 306, di column_or_1d naikkan ValueError ("bentuk input buruk { 0} ". Format (bentuk)) ValueError: bentuk input buruk (6, 3)
Adakah pemikiran tentang bagaimana mengatasi masalah ini?
sumber
dataframe
data string. Saya mem-piclking objek pengkodean, jadi saya ingin menghindari keharusan untuk acar / membongkar 50 objek yang terpisah. Juga, saya bertanya-tanya apakah ada cara untuk membuat encoder menyederhanakan data, yaitu hanya mengembalikan satu baris dengan pengenal untuk setiap kombinasi variabel yang unik di setiap kolom.replace
metode. Lihat jawaban di bawah iniJawaban:
Anda dapat dengan mudah melakukan ini,
EDIT2:
Di scikit-belajar 0,20, cara yang disarankan adalah
karena OneHotEncoder sekarang mendukung input string. Menerapkan OneHotEncoder hanya ke kolom tertentu dimungkinkan dengan ColumnTransformer.
EDIT:
Karena jawaban ini lebih dari setahun yang lalu, dan menghasilkan banyak upvote (termasuk hadiah), saya mungkin harus memperpanjang ini lebih jauh.
Untuk inverse_transformasi dan transformasi, Anda harus melakukan sedikit peretasan.
Dengan ini, Anda sekarang mempertahankan semua kolom
LabelEncoder
sebagai kamus.sumber
df.apply(LabelEncoder().fit_transform)
?LabelBinarizer
dan menggunakan kembali kamus untuk set tes? Aku mencobad = defaultdict(LabelBinarizer)
dan kemudianfit = df.apply(lambda x: d[x.name].fit_transform(x))
tapi eksepsi dimunculkan:Exception: Data must be 1-dimensional
. Saya tidak yakin bagaimana saya mengharapkan DataFrame yang dihasilkan terlihat seperti ... mungkin setiap kolom harus memegang vektor binarized.Seperti yang disebutkan oleh larsmans, LabelEncoder () hanya menggunakan array 1-d sebagai argumen . Yang mengatakan, sangat mudah untuk roll encoder label Anda sendiri yang beroperasi pada beberapa kolom yang Anda pilih, dan mengembalikan kerangka data yang diubah. Kode saya di sini sebagian didasarkan pada posting blog Zac Stewart yang sangat baik yang ditemukan di sini .
Membuat encoder kustom melibatkan hanya menciptakan kelas yang merespon dengan
fit()
,transform()
, danfit_transform()
metode. Dalam kasus Anda, awal yang baik mungkin seperti ini:Misalkan kita ingin menyandikan dua atribut kategoris kita (
fruit
dancolor
), sambil membiarkan atribut numerikweight
saja. Kita bisa melakukan ini sebagai berikut:Yang mengubah
fruit_data
dataset kami dariuntuk
Melewatkannya kerangka data yang seluruhnya terdiri dari variabel kategorikal dan menghilangkan
columns
parameter akan menghasilkan setiap kolom yang dikodekan (yang saya percaya adalah apa yang awalnya Anda cari):Ini mengubah
untuk
.
Perhatikan bahwa itu mungkin akan tersedak ketika mencoba untuk menyandikan atribut yang sudah numerik (tambahkan beberapa kode untuk menangani ini jika Anda suka).
Fitur bagus lain tentang ini adalah bahwa kita dapat menggunakan transformator khusus ini dalam sebuah pipa:
sumber
Karena scikit-learn 0.20 Anda dapat menggunakan
sklearn.compose.ColumnTransformer
dansklearn.preprocessing.OneHotEncoder
:Jika Anda hanya memiliki variabel kategori,
OneHotEncoder
langsung:Jika Anda memiliki fitur yang diketik secara heterogen:
Opsi lainnya dalam dokumentasi: http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogeneous-data
sumber
inverse_transform()
tidak didukung di ColumnTransformer. Setidaknya, tidak untuk saat ini: github.com/scikit-learn/scikit-learn/issues/11463 . Itu kerugian besar untuk aplikasi saya, dan mungkin juga untuk orang lain.Kami tidak membutuhkan LabelEncoder.
Anda dapat mengonversi kolom ke kategori dan kemudian mendapatkan kodenya. Saya menggunakan pemahaman kamus di bawah ini untuk menerapkan proses ini pada setiap kolom dan membungkus hasilnya kembali ke dalam kerangka data dengan bentuk yang sama dengan indeks dan nama kolom yang identik.
Untuk membuat kamus pemetaan, Anda bisa menghitung kategori menggunakan pemahaman kamus:
sumber
ini tidak langsung menjawab pertanyaan Anda (yang memiliki balasan fantastis Naputipulu Jon dan PriceHardman)
Namun, untuk tujuan beberapa tugas klasifikasi dll, Anda dapat menggunakan
ini dapat memasukkan kerangka data dengan data kategorikal dan mengembalikan kerangka data dengan nilai biner. nilai variabel dikodekan menjadi nama kolom di dalam dataframe yang dihasilkan. lebih
sumber
Dengan asumsi Anda hanya mencoba untuk mendapatkan
sklearn.preprocessing.LabelEncoder()
objek yang dapat digunakan untuk mewakili kolom Anda, yang harus Anda lakukan adalah:Dalam kode di atas Anda akan memiliki nomor unik yang sesuai dengan setiap kolom. Lebih tepatnya, Anda akan memiliki pemetaan 1: 1
df.columns
untukle.transform(df.columns.get_values())
. Untuk mendapatkan penyandian kolom, cukup kirimkan kele.transform(...)
. Sebagai contoh, berikut ini akan mendapatkan pengkodean untuk setiap kolom:Dengan asumsi Anda ingin membuat
sklearn.preprocessing.LabelEncoder()
objek untuk semua label baris Anda, Anda dapat melakukan hal berikut:Dalam hal ini, Anda kemungkinan besar memiliki label baris yang tidak unik (seperti yang ditunjukkan dalam pertanyaan Anda). Untuk melihat kelas apa yang dibuat oleh encoder, Anda dapat melakukannya
le.classes_
. Anda akan perhatikan bahwa ini harus memiliki elemen yang sama dengan diset(y for x in df.get_values() for y in x)
. Sekali lagi untuk mengonversi label baris menjadi penggunaan label yang disandikanle.transform(...)
. Sebagai contoh, jika Anda ingin mengambil label untuk kolom pertama dalamdf.columns
array dan baris pertama, Anda bisa melakukan ini:Pertanyaan yang Anda miliki dalam komentar Anda sedikit lebih rumit, tetapi masih dapat diselesaikan:
Kode di atas melakukan hal berikut:
LabelEncoder
kelas yang tidak mendukung tupel sebagai nama kelas.LabelEncoder
.Sekarang untuk menggunakan model baru ini sedikit lebih rumit. Dengan asumsi kita ingin mengekstrak representasi untuk item yang sama seperti yang kita cari pada contoh sebelumnya (kolom pertama di df.columns dan baris pertama), kita dapat melakukan ini:
Ingat bahwa setiap pencarian sekarang merupakan representasi string dari tuple yang berisi (kolom, baris).
sumber
Tidak,
LabelEncoder
jangan lakukan ini. Dibutuhkan array 1-d label kelas dan menghasilkan array 1-d. Ini dirancang untuk menangani label kelas dalam masalah klasifikasi, bukan data yang arbitrer, dan setiap upaya untuk memaksanya ke dalam penggunaan lain akan memerlukan kode untuk mengubah masalah aktual menjadi masalah yang dipecahkannya (dan solusi kembali ke ruang asli).sumber
DataFrame
?LabelEncoder
kode dan sesuaikan. Saya sendiri tidak menggunakan Panda, jadi saya tidak tahu seberapa sulitnya itu.pandas
orang lain memecahkan pertanyaan ini juga - saya yakin saya bukan satu-satunya orang dengan tantangan ini, jadi saya berharap mungkin ada solusi pra-dibangun di luar sana.Ini adalah satu setengah tahun setelah fakta, tapi saya juga, perlu untuk dapat
.transform()
beberapa kolom dataframe panda sekaligus (dan dapat.inverse_transform()
juga). Ini berkembang atas saran luar biasa dari @PriceHardman di atas:Contoh:
Jika
df
dandf_copy()
merupakanpandas
kerangka data tipe campuran, Anda bisa menerapkannyaMultiColumnLabelEncoder()
kedtype=object
kolom dengan cara berikut:Anda dapat mengakses masing-masing kelas kolom, label kolom, dan penyandi kolom yang digunakan untuk menyesuaikan setiap kolom melalui pengindeksan:
mcle.all_classes_
mcle.all_encoders_
mcle.all_labels_
sumber
fit
metode dari atas yang tidak akan benar-benar menghasilkan label sampai Anda menerapkannya (transform
/fit_transform
) ke data.Menindaklanjuti komentar yang diangkat pada solusi @PriceHardman saya akan mengusulkan versi kelas berikut:
Kelas ini cocok dengan encoder pada set pelatihan dan menggunakan versi yang pas saat mentransformasikannya. Versi awal kode dapat ditemukan di sini .
sumber
Cara singkat ke
LabelEncoder()
beberapa kolom dengandict()
:dan Anda dapat menggunakan ini
le_dict
untuk memberi label Kode kolom lain:sumber
Adalah mungkin untuk melakukan ini semua dalam panda secara langsung dan sangat cocok untuk kemampuan unik dari
replace
metode ini.Pertama, mari kita membuat kamus kamus yang memetakan kolom dan nilainya ke nilai penggantian yang baru.
Karena ini akan selalu menjadi pemetaan satu-satu, kita dapat membalikkan kamus batin untuk mendapatkan pemetaan nilai-nilai baru kembali ke aslinya.
Sekarang, kita dapat menggunakan kemampuan unik dari
replace
metode untuk mengambil daftar kamus yang bersarang dan menggunakan kunci luar sebagai kolom, dan kunci dalam sebagai nilai yang ingin kita ganti.Kita dapat dengan mudah kembali ke aslinya dengan kembali merantai
replace
metodesumber
Setelah banyak pencarian dan percobaan dengan beberapa jawaban di sini dan di tempat lain, saya pikir jawaban Anda ada di sini :
Ini akan mempertahankan nama kategori di seluruh kolom:
sumber
Saya memeriksa kode sumber ( https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/preprocessing/label.py ) dari LabelEncoder. Itu didasarkan pada seperangkat transformasi numpy, yang salah satunya adalah np.unique (). Dan fungsi ini hanya membutuhkan input array 1-d. (koreksi saya jika saya salah).
Gagasan yang sangat kasar ... pertama, kenali kolom mana yang membutuhkan LabelEncoder, kemudian lewati setiap kolom.
Df yang dikembalikan akan menjadi yang setelah pengkodean, dan label_list akan menunjukkan kepada Anda apa arti semua nilai tersebut di kolom yang sesuai. Ini adalah cuplikan dari skrip proses data yang saya tulis untuk pekerjaan. Beri tahu saya jika Anda berpikir akan ada peningkatan lebih lanjut.
EDIT: Hanya ingin menyebutkan di sini bahwa metode di atas bekerja dengan bingkai data tanpa melewatkan yang terbaik. Tidak yakin bagaimana ini bekerja menuju bingkai data yang berisi data yang hilang. (Saya memiliki kesepakatan dengan prosedur yang hilang sebelum menjalankan metode di atas)
sumber
jika kita memiliki satu kolom untuk melakukan pengkodean label dan inversnya mengubah dengan mudah bagaimana melakukannya ketika ada banyak kolom dalam python
sumber
Jika Anda memiliki numerik dan kategorikal kedua jenis data dalam kerangka data Anda dapat menggunakan: di sini X adalah kerangka data saya yang kategorikal dan numerik kedua variabel
Catatan: Teknik ini bagus jika Anda tidak tertarik untuk mengubahnya kembali.
sumber
Menggunakan Neuraxle
Dengan metode ini, pembuat enkode label Anda akan dapat masuk dan bertransformasi dalam pipeline scikit-learn reguler . Mari kita impor:
Encoder bersama yang sama untuk kolom:
Berikut ini cara LabelEncoder yang dibagikan akan diterapkan pada semua data untuk menyandikannya:
Hasil:
Encoders berbeda per kolom:
Dan di sini adalah bagaimana LabelEncoder mandiri pertama akan diterapkan pada hewan peliharaan, dan yang kedua akan dibagikan untuk pemilik kolom dan lokasi. Jadi tepatnya, kami di sini memiliki campuran enkode label yang berbeda dan dibagikan:
Hasil:
sumber
Terutama digunakan jawaban @Alexander tetapi harus membuat beberapa perubahan -
Kemudian untuk digunakan kembali di masa depan Anda hanya dapat menyimpan output ke dokumen json dan ketika Anda membutuhkannya Anda membacanya dan menggunakan
.map()
fungsi seperti yang saya lakukan di atas.sumber
Masalahnya adalah bentuk data (pd dataframe) yang Anda lewati untuk fungsi fit. Anda harus melewati daftar 1d.
sumber
Di sini saya membaca csv dari lokasi dan dalam fungsi saya melewati daftar kolom saya ingin labelencode dan dataframe saya ingin menerapkan ini.
sumber
Bagaimana dengan ini?
Ini bukan yang paling efisien, namun bekerja dan sangat sederhana.
sumber