Método de transformação PySpark com Vector Assembler

Sep 26 2020

Eu tenho um Spark DataFrame e gostaria de usar o Vector Assembler para criar uma coluna de "recursos".

from pyspark.ml.feature import VectorAssembler

assembler = VectorAssembler(inputCols=sel_cols, outputCol='features')

transformed_data = assembler.transform(sdf)

sel_cols consiste em uma lista de 150 itens do tipo string, que se parece com o seguinte:

['ASP.NET Core',
 'ASP.NET MVC',
 'AWS',
 'AWS DynamoDB',
 'AWS EMR',
 'AWS SDK',
 'Adobe Photoshop',
 'Agile',
 'Agile software development29',
 'Ajax',
 'Amazon CloudFront CDN',
 'Amazon EC2',
 'Android',
 'Angular',
 'AngularJS',
 'Apache',
 'Apache Hive',
 'Apache Spark',
 'Atom',...]

E sdf.columns, consiste em 340 itens e tem a seguinte aparência:

['.NET',
 '.NET 4',
 '.NET Core',
 'ADO.NET',
 'AFNetworking',
 'API Architecture',
 'API Design',
 'API Development',
 'APIs',
 'ASP.NET',
 'ASP.NET Core',
 'ASP.NET MVC',
 'ASP.NET Web API',
 'AWS',
 'AWS DynamoDB',...]

Estou recebendo este erro ao aplicar transform_data = assembler.transform (sdf):

AnalysisException: Cannot resolve column name "ASP.NET Core" among (.NET, .NET 4, .NET Core, ADO.NET, AFNetworking, API Architecture, API Design, API Development, APIs, ASP.NET, ASP.NET Core, ASP.NET MVC, ASP.NET Web API, AWS, AWS DynamoDB, AWS EC2, AWS ECS, AWS EMR, AWS HA, AWS Lambda, AWS RDS, AWS S3, AWS SDK, Adobe Illustrator,...

Como mostrado, "ASP.NET Core" está definitivamente entre meus sdf.columns e, pelo que entendi, passar sel_cols como uma lista de string para inputCols de VectorAssembler deve funcionar ... Realmente apreciaria qualquer insight, pois não trabalhei com Spark DF antes :)

Obrigado!

Respostas

1 werner Sep 26 2020 at 22:56

O VectorAssembler não pode manipular colunas com um espaço ou um ponto no nome da coluna. Outra resposta minha fornece algum conhecimento técnico por que ele não funciona.

A única opção é renomear as colunas:

#build a dict (orginal column name: new column name)
mapping = {col: col.replace('.','_').replace(' ', '_') for col in sel_columns}

#select all columns and create an alias if there is a mapping for this column
df_renamed = df.select([F.col('`'+c+'`').alias(mapping.get(c, c)) for c in df.columns])

#create a VectorAssembler that uses the renamed columns as input
assembler = VectorAssembler(inputCols=list(mapping.values()), outputCol='features')
transformed_data = assembler.transform(df_renamed)