Чтобы RandomForestRegressor соответствовал числовым и категориальным столбцам, я хочу создать чистый конвейер.Я знаю, что мне нужно включить OneHotEncoding для обработки категориальных данных, но мне не удается правильно отформатировать все.
# Since I have either string or double column types, I can split my
# columns in two lists
cat_cols = [c for c, dtype in data.dtypes if dtype == 'string']
num_cols = [c for c in data.columns if c not in cat_cols]
Чтобы применить OneHotEncoding для категориальных данных, сначала мне нужно применить StringIndexing:
from pyspark.ml.feature import StringIndexer
indexers = [StringIndexer(inputCol=cat_var, outputCol=cat_var+'_indexed', handleInvalid='keep') for cat_var in cat_cols]
# These two lists are here to lighten the code
cat_indexed = [cat_var+"_indexed" for cat_var in cat_cols]
cat_encoded = [cat_var+"_encoded" for cat_var in cat_cols]
Начиная с версии 2.3, рекомендуется использовать OneHotEncoderEstimator .Проблема в том, что учебник не показывает, как объединить его со списком StringIndexers и превратить его в конвейер.
from pyspark.ml.feature import OneHotEncoderEstimator
encoder = OneHotEncoderEstimator(inputCols=cat_indexed, outputCols=cat_encoded)
# with version < 2.3 it would have been:
# encoders = [OneHotEncoder(inputCol=x, outputCol=y) for x,y in zip(cat_indexed, cat_encoded)]
Завершение всего с помощью Pipeline :
from pyspark.ml import Pipeline
from pyspark.ml.features import VectorAssembler
# I have to get my numerical columns back:
cols_now = cat_encoded + num_cols
assembler = VectorAssembler(inputCols=cols_now, outputCol='features')
# If my target variable had been a string, I would have apply StringIndexing for this also:
labelIndexer = StringIndexer(inputCol='target_var', outpuCol='label')
# I need to concatenate a list of indexers, encoders, the vector assembler and my target_var
# What I would do if I had a list of encoders with the deprecated function OneHotEncoder:
tmp = [[i,j] for i,j in zip(indexers, encoders)]
tmp = [i for sublist in tmp for i in sublist]
tmp += [assembler, labelIndexer]
pipeline = Pipeline(stages=tmp)
Но:
- У меня есть объект кодировщика, а не повторяемый, поэтому приведенный выше код не будет работать
- Моя целевая переменная является числовой, поэтому я должен просто добавить ее в необработанном виде вместо labelIndexer?