对对象,sklearn管道的两列应用不同的转换
applying different transformation to two columns which are object, sklearn pipeline
我正在尝试将两种不同的转换从 sklearn 应用到两个不同的列,它们都是 object
在我的 Pipeline
中。我的 DataFrame
看起来像这样(我避免所有行只是为了说明我的观点):
email country label
fulanito@gmail.com NI True
fipretko@gmail.com AR False
trytryyy@gmail.com CZ True
email
和country
都是object
类型
对于 email
我创建了一堆函数来将它转换成它的一些数字表示。
喜欢:
def email_length(email) -> np.array:
return np.array([len(e[0].split('@')[0]) for e in email]).reshape(-1, 1)
def domain_length(email) -> np.array:
return np.array([len(e[0].split('@')[-1]) for e in email]).reshape(-1, 1)
def number_of_vouls(email) -> np.array:
vouls = 'aeiouAEIOU'
name = [e[0].split('@')[0] for e in email]
return np.array([sum(1 for char in name if char in vouls) for name in name]).reshape(-1, 1)
为了将函数传递给 sklearn Pipeline
中的 email
,我使用了 FunctionTransformer
和 FeatureUnion
,就像这样。
get_email_length = FunctionTransformer(email_length)
get_domain_length = FunctionTransformer(domain_length)
get_number_of_vouls = FunctionTransformer(number_of_vouls)
preproc = FeatureUnion([
('email_length', get_email_length),
('domain_length', get_domain_length),
('number_of_vouls', get_number_of_vouls)])
pipe = Pipeline([
('preproc', preproc),
('classifier', LGBMClassifier())
])
但我也想在我的 Pipeline
内部传递一个单热编码器到 country
,鉴于此 Pipeline
定义,这将是最好的方法吗?
你可以试试 ColumnTransformer:
1。使用 DataFrame 输入
def email_and_domain_length(df: pd.DataFrame) -> pd.DataFrame:
return df["email"].str.split("@", expand=True).applymap(len)
def number_of_vouls(df: pd.DataFrame) -> pd.DataFrame:
return (
df["email"]
.str.split("@")
.str[0]
.str.lower()
.apply(lambda x: sum(x.count(v) for v in "aeiou"))
.to_frame()
)
get_email_length = FunctionTransformer(email_and_domain_length)
get_number_of_vouls = FunctionTransformer(number_of_vouls)
preproc = ColumnTransformer(
[
("lengths", get_email_length, ["email"]),
("vouls", get_number_of_vouls, ["email"]),
("countries", OneHotEncoder(), ["country"]),
]
)
preproc.fit_transform(df[["email", "country"]])
2。使用 ndarray 输入:
只需将其添加到您问题中的代码中,它已经适用于 ndarray 输入。
preproc = ColumnTransformer(
[
("email_lengths", get_email_length, [0]),
("voul_lengths", get_domain_length, [0]),
("vouls", get_number_of_vouls, [0]),
("countries", OneHotEncoder(), [1]),
]
)
preproc.fit_transform(df[["email", "country"]].to_numpy())
输出:
array([[8., 9., 4., 0., 0., 1.],
[8., 9., 3., 1., 0., 0.],
[8., 9., 0., 0., 1., 0.]])
顺便说一句,如果 country
具有高基数,one-hot-encoding 弊大于利。
我还尝试使用 .str 访问器方法而不是列表理解来向量化预处理函数。
我正在尝试将两种不同的转换从 sklearn 应用到两个不同的列,它们都是 object
在我的 Pipeline
中。我的 DataFrame
看起来像这样(我避免所有行只是为了说明我的观点):
email country label
fulanito@gmail.com NI True
fipretko@gmail.com AR False
trytryyy@gmail.com CZ True
email
和country
都是object
类型
对于 email
我创建了一堆函数来将它转换成它的一些数字表示。
喜欢:
def email_length(email) -> np.array:
return np.array([len(e[0].split('@')[0]) for e in email]).reshape(-1, 1)
def domain_length(email) -> np.array:
return np.array([len(e[0].split('@')[-1]) for e in email]).reshape(-1, 1)
def number_of_vouls(email) -> np.array:
vouls = 'aeiouAEIOU'
name = [e[0].split('@')[0] for e in email]
return np.array([sum(1 for char in name if char in vouls) for name in name]).reshape(-1, 1)
为了将函数传递给 sklearn Pipeline
中的 email
,我使用了 FunctionTransformer
和 FeatureUnion
,就像这样。
get_email_length = FunctionTransformer(email_length)
get_domain_length = FunctionTransformer(domain_length)
get_number_of_vouls = FunctionTransformer(number_of_vouls)
preproc = FeatureUnion([
('email_length', get_email_length),
('domain_length', get_domain_length),
('number_of_vouls', get_number_of_vouls)])
pipe = Pipeline([
('preproc', preproc),
('classifier', LGBMClassifier())
])
但我也想在我的 Pipeline
内部传递一个单热编码器到 country
,鉴于此 Pipeline
定义,这将是最好的方法吗?
你可以试试 ColumnTransformer:
1。使用 DataFrame 输入
def email_and_domain_length(df: pd.DataFrame) -> pd.DataFrame:
return df["email"].str.split("@", expand=True).applymap(len)
def number_of_vouls(df: pd.DataFrame) -> pd.DataFrame:
return (
df["email"]
.str.split("@")
.str[0]
.str.lower()
.apply(lambda x: sum(x.count(v) for v in "aeiou"))
.to_frame()
)
get_email_length = FunctionTransformer(email_and_domain_length)
get_number_of_vouls = FunctionTransformer(number_of_vouls)
preproc = ColumnTransformer(
[
("lengths", get_email_length, ["email"]),
("vouls", get_number_of_vouls, ["email"]),
("countries", OneHotEncoder(), ["country"]),
]
)
preproc.fit_transform(df[["email", "country"]])
2。使用 ndarray 输入:
只需将其添加到您问题中的代码中,它已经适用于 ndarray 输入。
preproc = ColumnTransformer(
[
("email_lengths", get_email_length, [0]),
("voul_lengths", get_domain_length, [0]),
("vouls", get_number_of_vouls, [0]),
("countries", OneHotEncoder(), [1]),
]
)
preproc.fit_transform(df[["email", "country"]].to_numpy())
输出:
array([[8., 9., 4., 0., 0., 1.],
[8., 9., 3., 1., 0., 0.],
[8., 9., 0., 0., 1., 0.]])
顺便说一句,如果 country
具有高基数,one-hot-encoding 弊大于利。
我还尝试使用 .str 访问器方法而不是列表理解来向量化预处理函数。