Método de transformación PySpark con Vector Assembler

Sep 26 2020

Tengo un Spark DataFrame y me gustaría usar Vector Assembler para crear una columna de "características".

from pyspark.ml.feature import VectorAssembler

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

transformed_data = assembler.transform(sdf)

sel_cols consta de una lista de 150 elementos de tipo cadena, que se ve como sigue:

['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',...]

Y sdf.columns, consta de 340 elementos y tiene el siguiente aspecto:

['.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',...]

Recibo este error al aplicar transform_data = assembly.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 se muestra, "ASP.NET Core" está definitivamente entre mis sdf.columns y, por lo que yo entiendo, pasar sel_cols como una lista de cadenas a inputCols de VectorAssembler debería funcionar ... Realmente agradecería cualquier información ya que no he trabajado con Spark DF's antes :)

¡Gracias!

Respuestas

1 werner Sep 26 2020 at 22:56

VectorAssembler no puede manejar columnas con un espacio o un punto en el nombre de la columna. Otra respuesta mía proporciona algunos antecedentes técnicos por qué no funciona.

La única opción es cambiar el nombre de las columnas:

#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)