يعد الحصول على get_dummies () في Pandas أمرًا رائعًا حقًا ، ولكن لكي تكون مفيدة للتعلم الآلي ، يجب أن تكون قابلة للاستخدام في إطار عمل تدريب / اختبار (أو "fit_transform" و "تحويل" ، باستخدام مصطلحات sklearn). اسمحوا لي أن أعرف إذا كان هذا يحتاج إلى مزيد من التفسيرات.
لذلك ، أعتقد أن هذا تقرير بقائمة الرغبات لإضافة هذه الوظيفة إلى Pandas. يمكنني حتى إنشاء طلب سحب ، إذا اتفق الناس على أن هذا سيكون شيئًا مفيدًا في Pandas (ولديهم الرغبة في التدريب قليلاً والقيام بمراجعة الكود لما ستكون مساهمتي الأولى في هذا المشروع).
حسنًا ، ماذا عن مثال كود زائف مع مدخلات ومخرجات من إطار عينة سيكون مفيدًا
@ chrish42 ، سيكون المثال رائعًا.
لدى FYI 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 () إلى مجموعة بيانات ، ثم تطبيق التحويل المذكور كما هو (إنشاء نفس الأعمدة بالضبط) ، حتى لو كانت مجموعة البيانات الثانية تحتوي على مجموعة فرعية من قيم المجموعة الأولى في بعض الأعمدة ، إلخ. هذا ما قصدته في الواقع بعبارة "قابلة للاستخدام في إطار تدريب / اختبار". هل هذا التفسير أوضح؟ (يمكنني إضافة مثال يعتقد شخص ما أنه لا يزال مطلوبًا.)
أنا على دراية بفئة OneHotEncoder
في sklearn ، لكن لها قيود أخرى.
لقد عثرت على نفس المشكلة مثل @ chrish42 ووجدت أن get_dummies تسبب لي بعض الصداع.
لنفترض أننا نعمل مع البيانات من df_train DataFrame التالي
"". بايثون
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_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
"". بايثون
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
""
ونتوقع أن تعيد 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.
القليل من النصائح غير المرغوب فيها. إذا كنت مهتمًا على الإطلاق بالتقديرات الدقيقة للمعاملات في الفئات ، فقم بإسقاط أحد الأعمدة المشفرة وإلا فسيكون لديك خط متعدد الخطوط مع التقاطع (إذا كان لديك واحد).
في 5 أكتوبر 2015 ، في الساعة 05:34 ، كتب Jeff Reback [email protected] :
تحتاج ببساطة إلى جعل المتغيرات الخاصة بك فئوية إذا كنت تريد تحديد متغيرات ربما لا يتم ملاحظتها. يمكن القيام بذلك في وقت الإنشاء أو بعد ذلك ، راجع المستندات
في [5]: df_train = pd.DataFrame ({"car": Series (["seat"، "bmw"]). astype ('category'، categories = ['seat'، 'bmw'، 'mercedes'] ) ، "اللون": ["أحمر" ، "أخضر"]})
في [6]: df_train
خارج [6]:
لون السيارة
0 مقعد أحمر
1 بي ام دبليو خضراءفي [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.
TomAugspurgerjreback أعتقد أنني واجهت نفس المشكلة في الآونة الأخيرة، وأنا أود أن أذكر مثالا
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']})
طباعة pd.get_dummies (test_a ، الأعمدة = ['Make'])
Make_BMW Make_Toyota
0 0 1
1 1 0
من الناحية المثالية ، يجب الحفاظ على عمود Make_Mazda لأن خوارزمية ML تتوقع نفس عدد الميزات والقيم التي نحصل عليها في الاختبار ستكون مجموعة فرعية من ذلك في القطار.
استخدم ملف. سيؤدي ذلك إلى توسيع العدد الصحيح من الأعمدة. لقد تحدثت عن هذا إذا كنت مهتمًا https://m.youtube.com/watch؟v=KLPtEBokqQ0
_____________________________
من: Ajay Saxena [email protected]
تاريخ الإرسال: الخميس 12 يناير 2017 الساعة 18:31
الموضوع: Re: [pandas-dev / pandas] قائمة الرغبات: اجعل get_dummies () قابلة للاستخدام في إطار التدريب / الاختبار (# 8918)
إلى: pandas -dev /
نسخة إلى: Tom Augspurger [email protected] ، أذكر [email protected]
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']})
طباعة pd.get_dummies (test_a ، الأعمدة = ['Make'])
Make_BMW Make_Toyota
0 0 1
1 1 0
من الناحية المثالية ، يجب الحفاظ على عمود Make_Mazda لأن خوارزمية ML تتوقع نفس عدد الميزات والقيم التي نحصل عليها في الاختبار ستكون مجموعة فرعية من ذلك في القطار.
-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.
TomAugspurger شكرا
حديث PyData Chicago 2016 الذي قدمه @ TomAugspurger كان جيدًا حقًا. لقد قام بعمل رائع في توضيح جميع أسباب عدم إغلاق هذه المشكلة / الطلب. يجب تضمين IMHO إما فئته DummyEncoder أو بعض المكافئ المعقول في Pandas المناسب. نعم يمكنني الذهاب إلى جيثب الخاص به ونسخ / محاكاة فصله ولكن سيكون من الأجمل بكثير أن يتم دعمه داخل المكتبة.
أعتقد أن هناك حاجة إلى مكتبة تعمل مبكرًا في نمذجة البيانات
خط أنابيب ويعمل بشكل جيد مع الباندا و scikit-Learn.
لكن الباندا لا تعتمد على scikit-Learn والعكس صحيح. أعتقد أن هناك
غرفة لمكتبة أخرى مبنية فوق كليهما.
يوم الأربعاء ، 10 مايو ، 2017 الساعة 6:13 مساءً ، Brian Wylie [email protected]
كتب:
حديث PyData Chicago 2016 الذي قدمه @ TomAugspurger
https://github.com/TomAugspurger كان جيدًا حقًا. لقد فعل
عمل رائع لتوضيح جميع الأسباب التي تجعل هذه المشكلة / الطلب يجب
لا تكون مغلقة. IMHO إما صفه DummyEncoder أو بعض المعقول
يجب تضمين ما يعادلها في Pandas المناسبة. نعم يمكنني الذهاب إلى جيثب الخاص به
ونسخ / محاكاة فصله ولكن سيكون من الأجمل بكثير الحصول عليه فقط
مدعوم داخل المكتبة.راجع للشغل أعتقد أن TomAugspurger https://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
لقد خلقت حلاً قد يكون مفيدًا بالضبط في هذه المشكلة. أحد المتغيرات القاطعة ذات التشفير الساخن في إطار اختبار القطار. يمكنه أيضًا التعامل مع الحالات التي تكون فيها مجموعة البيانات كبيرة جدًا بحيث لا يمكن وضعها في ذاكرة الجهاز.
https://github.com/yashu-seth/dummyPy
يمكنك أيضًا العثور على برنامج تعليمي صغير حول هذا هنا .
قد يكون الأشخاص المشتركون في هذا مهتمين بتنفيذ dask-ml
TomAugspurger هذا الرمز لا يعمل. عندما أذهب لتحويل بيانات الإنتاج الفردي الخاصة بي ، لا يعطيني سوى عمود واحد مشفر ساخن للقيمة الفردية الموجودة.
ماذا ينقصني؟
استيراد ملفات pyodbc
مخلل استيراد
من sklearn.linear_model استيراد LogisticRegression
من sklearn.linear_model استيراد LinearRegression
استيراد numpy كـ np
استيراد الباندا كما pd
من sklearn.pipeline استيراد TransformerMixin
من sklearn.pipeline استيراد make_pipeline
فئة DummyEncoder (TransformerMixin):
تناسب def (ذاتي ، X ، ص = لا شيء):
مؤشر self.index_ = X.index
self.columns_ = X.columns
self.cat_columns_ = X.select_dtypes (تشمل = ['category']). أعمدة
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 = "" "
حدد أعلى 1 CONVERT (int، [order_key]) order_key
، CONVERT (int، [service_date_key]) service_date_key
، [order_source_desc]
، 1 كـ "return_flag"
من [ML_Return_Customer]. [dbo]. [return_customers_test_set]
أين [order_source_desc] = "متصل"
اتحاد
حدد أهم 2 CONVERT (int، [order_key])
، CONVERT (int، [service_date_key])
، [order_source_desc]
، 2
من [ML_Return_Customer]. [dbo]. [return_customers_test_set]
أين [order_source_desc] = "مكالمة واردة"
اتحاد
حدد أفضل 1 CONVERT (int، [order_key])
، CONVERT (int، [service_date_key])
، [order_source_desc]
، 1
من [ML_Return_Customer]. [dbo]. [return_customers_test_set]
أين [order_source_desc] = "مكالمة صادرة"
""
prod_sql = "" "
حدد أعلى 1 CONVERT (int، [order_key]) order_key
، CONVERT (int، [service_date_key]) service_date_key
، [order_source_desc]
، 1 كـ "return_flag"
من [ML_Return_Customer]. [dbo]. [return_customers_test_set]
أين [order_source_desc] = "متصل"
""
InputDataSet = pd.read_sql (sql، cnxn)
ProdDataSet = pd.read_sql (prod_sql، cnxn)
طباعة (" * * * * بيانات
* * * * * ")print (" * معلومات أعمدة الفئات
* * ")InputDataSet.info ()
طباعة (" * الانحدار الخطي
* * ")X = InputDataSet.drop ('return_flag' ، المحور = 1)
y = InputDataSet ['return_flag']
أ = ProdDataSet.drop ('return_flag' ، المحور = 1)
B = ProdDataSet ['return_flag']
enc = DummyEncoder ()
enc.fit (X)
إنتاج = enc.transform (A)
طباعة (إنتاج)
الإخراج: * * * * البيانات
* * * *لذلك أعتقد أن هذا الخيط فوضوي بعض الشيء ، لذا سأحاول تلخيص حل بسيط هنا وكيف أن هذا ممكن بالفعل. سأشرح في عمود واحد ، لكن يمكنك تعميمها على كثيرين.
لذا في "fit" ، اتصل فقط بما يلي:
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 أثناء الاختبار. إذا لم يتم رؤية بعض القيم أثناء الاختبار ، فلن يتم تعيين أي عمود لها.
هذا لطيف جدا. أتمنى ألا يضطر كل من يريد القيام بذلك إلى اكتشافه من جديد. ؛-)
النهج الذي اقترحه mitar هو مثال قصير لطيف. لاستكشاف هذه المشكلة لفترة أطول ، إليك دفتر ملاحظات قد يكون مفيدًا / مفيدًا: https://nbviewer.jupyter.org/github/SuperCowPowers/scp-labs/blob/master/notebooks/Categorical_Encoding_Dangers.ipynb
شاهد الكود أدناه في ممارسة برنامج Kaggle XGBoost التعليمي. هذه هي الحيلة.
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
ملاحظة: لن يعتني ذلك بأي استثناءات ، مثل تمرير أسماء الأعمدة غير المتوفرة في إطار البيانات
التعليق الأكثر فائدة
تحتاج ببساطة إلى جعل المتغيرات الخاصة بك
Categorical
إذا كنت تريد تحديد المتغيرات التي لا يمكن ملاحظتها _ربما _. يمكن القيام بذلك في وقت الإنشاء أو بعد ذلك ، راجع المستنداتالسؤال الأصلي غير محدد جيدًا ، لذا خاتمة.