Pandas 如何创建自己的自定义转换器并在scikit learn中的管道中使用它们?
我是机器学习新手,所以如果问题很傻,我的代码没有多大意义,我会提前道歉 我从kaggle下载了泰坦尼克号的数据集,希望创建一个分类器模型,根据几个重要特征预测乘客是否幸存。其中一些重要特征是:Pandas 如何创建自己的自定义转换器并在scikit learn中的管道中使用它们?,pandas,scikit-learn,data-science,Pandas,Scikit Learn,Data Science,我是机器学习新手,所以如果问题很傻,我的代码没有多大意义,我会提前道歉 我从kaggle下载了泰坦尼克号的数据集,希望创建一个分类器模型,根据几个重要特征预测乘客是否幸存。其中一些重要特征是: 名字 性 年龄 船舱 票 船舱 登船 以下是数据的外观: 其中一些功能的值为空,或者我想在对列进行编码之前对其进行修改(例如,名称列我只想使用字符串“Mr”、“Mrs”而不是其全名) 我知道如何通过使用正常的熊猫操作(如fillna()等)来完成所有这些操作。。。但是我想创建一个管道和一个列转换器,这样
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
# Fill empty age values with median
median_pipeline = Pipeline([
('imputer', SimpleImputer(strategy='median'))
])
# Fill cabin and embarked with 'U'
fill_pipeline = Pipeline([
('fill_U', SimpleImputer(strategy='constant', fill_value='U'))
])
在这里,我还将创建一个自定义转换器来修改名称,使其仅为“mr”、“mrs”等。。这段代码可能是错误的,我不确定我需要从transform返回什么
from sklearn.base import BaseEstimator, TransformerMixin
class change_name(BaseEstimator, TransformerMixin):
def __init__(self, modify_name=True):
self.modify_name = modify_name
def fit(self, X,y=None):
return self
def transform(self, X, y=None):
if self.modify_name:
X['Name'] = X['Name'].apply(lambda x: x.split()[1].replace('.', ''))
return X
接下来,我创建一个新列,以确定具有票证Id的人员是否单独旅行:
来自sklearn.base导入BaseEstimator,TransformerMixin
class create_multiple_ticket(BaseEstimator, TransformerMixin):
tickets = {}
for ticket, num in X.Ticket.value_counts().items():
if num > 1:
tickets[ticket] = 1
def __init__(self, change=True):
self.change=True
self.tickets = tickets
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
if self.change:
# Creating a new column of boolean values
X['multiple_tickets'] = X['Ticket'].apply(lambda x: x in tickets)
return X.drop('Ticket', axis=1)
下一步,我只得到船舱的下标是一个字母
class modify_cabin(BaseEstimator, TransformerMixin):
def __init__(self, modify=True):
self.modify = True
def fit(self, X, y=None):
return self
def transform(self, X, y=None):
if self.modify:
X['Cabin'] = X['Cabin'].apply(lambda x: x[0])
return X
最后,我创建了我的管道
ticket_pipeline = Pipeline([
('modify_ticket', create_multiple_ticket())
])
name_pipeline = Pipeline([
('modify_name', change_name())
])
cabin_pipeline = Pipeline([
('modify_cabin', modify_cabin())
])
最后我使用了柱状变压器
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
median_attributes = ['Age']
fill_attributes = ['Cabin', 'Embarked']
onehot_encoded_attributes = ['Cabin', 'Name', 'Embarked', 'Sex']
full_pipeline = ColumnTransformer([
('age', median_pipeline, median_attributes), # fill empty values with age median
('fill', fill_pipeline, fill_attributes), # fill 'Cabin' and 'Embarked' with 'U value'
('name', name_pipeline, ['Name']), # Converts name column to just 'Mr', 'Miss' etc...
('ticket', ticket_pipeline, ['Ticket']), # Creates a new column called multiple tickets and returns true or false
('cabin', cabin_pipeline, ['Cabin']), # Cabin column gets modified to just one letter.
('categorical', OneHotEncoder(), onehot_encoded_attributes) # One_hot encodes the attributes
], remainder='passthrough')
X_train_prepared = full_pipeline.fit_transform(X_train)
X_train_prepared
现在,当我运行上面的代码时,我得到以下错误:
<ipython-input-68-a83b52eb52ee> in <lambda>(x)
8 def transform(self, X, y=None):
9 if self.modify:
---> 10 X['Cabin'] = X['Cabin'].apply(lambda x: x[0])
11 return X
TypeError: 'float' object is not subscriptable
in(x)
8 def变换(自、X、y=无):
9如果自行修改:
--->10 X['Cabin']=X['Cabin']。适用(λX:X[0])
11返回X
TypeError:“float”对象不可下标
这是因为座舱仍然具有NaN值,因此您不能下标NaN。但是在我的管道中,在运行CAB_管道之前,我应该首先使用SimpleImputer将空CAB值填充为'U'。为什么它还在这样做
两个问题:
非常感谢您的帮助 ColumnTransformer不按顺序执行转换 Columntransformer中的步骤应应用于特定列,而不是列上的单个转换。 若您需要在一列上进行多重转换,那个么应该首先将它们打包到管道中,然后在ColumnTransformer中运行它 希望有帮助 我在这里找到了一些很好的例子: