我遇到的情况是我需要在管道中执行某些列特定的处理,但是由于转换器返回numpy数组而不是pandas数据帧,因此我没有列名来进行功能设计。
这是一个简单的,可复制的示例,其中有一个engineer_feature
我想用来创建新数据的函数。我需要在流水线期间/之后使用它,因为它取决于插补的一列,我希望能够在k倍交叉验证期间执行它。
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import FunctionTransformer, OneHotEncoder, StandardScaler
df = pd.DataFrame({"Type": ["Beta", "Beta", "Alpha", "Charlie", "Beta", "Charlie"], "A": [1, 2, 3, np.nan, 22, 4], "B": [5, 7, 12, 21, 12, 10]})
def engineer_feature(df):
df["C"] = df["A"] / df["B"]
return df
categorical_transformer = Pipeline([
("one_hot", OneHotEncoder())
])
numeric_transformer = Pipeline([
("imputer", SimpleImputer()),
("engineer", FunctionTransformer(engineer_feature)),
("scaler", StandardScaler())
])
preprocessor = ColumnTransformer([
("categorical", categorical_transformer, ["Type"]),
("numeric", numeric_transformer, ["A", "B"])
])
preprocessor.fit_transform(df)
产生此错误:
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
这是有道理的,因为engineer_feature
当它们只是numpy数组时,试图将它们好像是数据帧一样对索引建立索引。
解决这个问题的策略是什么?我不想对列索引进行硬编码以通过numpy访问它们,特别是因为我的实际数据框具有更多列。
感谢尼克和谢尔盖(Nick and Sergey)的讨论和回答(特别是我确实知道要传入数据框的哪些列engineer_feature
),因此我想出了一个我可以接受的解决方案;但是,如果有人有更好的主意,请发出提示。
import numpy as np
import pandas as pd
from functools import partial
from sklearn.compose import ColumnTransformer
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import FunctionTransformer, OneHotEncoder, StandardScaler
df = pd.DataFrame({"Type": ["Beta", "Beta", "Alpha", "Charlie", "Beta", "Charlie"], "A": [1, 2, 3, np.nan, 22, 4], "B": [5, 7, 12, 21, 12, 10]})
def engineer_feature(columns, X):
df = pd.DataFrame(X, columns=columns)
df["C"] = df["A"] / df["B"]
return df
categorical_transformer = Pipeline([
("one_hot", OneHotEncoder())
])
def numeric_transformer(columns):
transformer = Pipeline([
("imputer", SimpleImputer()),
("engineer", FunctionTransformer(partial(engineer_feature, columns))),
("scaler", StandardScaler())
])
return ("numeric", transformer, columns)
preprocessor = ColumnTransformer([
("categorical", categorical_transformer, ["Type"]),
numeric_transformer(["A", "B"])
])
preprocessor.fit_transform(df)
这取决于两个列,A
并且B
每个值至少具有一个值,这样SimpleImputer
就不会丢失该列,这毫无价值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句