web-dev-qa-db-fra.com

Comment changer les noms de colonne de dataframe dans pyspark?

Je viens de fond de pandas et je suis habitué à lire des données de fichiers CSV dans un cadre de données, puis à changer simplement les noms des colonnes pour les rendre utiles en utilisant la simple commande:

df.columns = new_column_name_list

Cependant, la même chose ne fonctionne pas dans les cadres de données pyspark créés avec sqlContext. La seule solution que je pourrais trouver pour le faire facilement est la suivante:

df = sqlContext.read.format("com.databricks.spark.csv").options(header='false', inferschema='true', delimiter='\t').load("data.txt")
oldSchema = df.schema
for i,k in enumerate(oldSchema.fields):
  k.name = new_column_name_list[i]
df = sqlContext.read.format("com.databricks.spark.csv").options(header='false', delimiter='\t').load("data.txt", schema=oldSchema)

En gros, il s'agit de définir deux fois la variable et d'inférer le schéma en premier, puis de renommer les noms de colonne, puis de charger à nouveau le cadre de données avec le schéma mis à jour. 

Existe-t-il un moyen plus efficace et plus efficace de procéder comme nous le faisons avec les pandas?

Ma version d'allumage est 1.5.0

95
Shubhanshu Mishra

Il y a plusieurs façons de le faire: 

  • Option 1. Utilisez selectExpr .

    data = sqlContext.createDataFrame([("Alberto", 2), ("Dakota", 2)], 
                                      ["Name", "askdaosdka"])
    data.show()
    data.printSchema()
    
    # Output
    #+-------+----------+
    #|   Name|askdaosdka|
    #+-------+----------+
    #|Alberto|         2|
    #| Dakota|         2|
    #+-------+----------+
    
    #root
    # |-- Name: string (nullable = true)
    # |-- askdaosdka: long (nullable = true)
    
    df = data.selectExpr("Name as name", "askdaosdka as age")
    df.show()
    df.printSchema()
    
    # Output
    #+-------+---+
    #|   name|age|
    #+-------+---+
    #|Alberto|  2|
    #| Dakota|  2|
    #+-------+---+
    
    #root
    # |-- name: string (nullable = true)
    # |-- age: long (nullable = true)
    
  • Option 2. En utilisant withColumnRenamed , notez que cette méthode vous permet "d'écraser" la même colonne.

    oldColumns = data.schema.names
    newColumns = ["name", "age"]
    
    df = reduce(lambda data, idx: data.withColumnRenamed(oldColumns[idx], newColumns[idx]), xrange(len(oldColumns)), data)
    df.printSchema()
    df.show()
    
  • Option 3. using alias , dans Scala, vous pouvez également utiliser as .

    from pyspark.sql.functions import *
    
    data = data.select(col("Name").alias("name"), col("askdaosdka").alias("age"))
    data.show()
    
    # Output
    #+-------+---+
    #|   name|age|
    #+-------+---+
    #|Alberto|  2|
    #| Dakota|  2|
    #+-------+---+
    
  • Option 4. Utilisation de sqlContext.sql , qui vous permet d’utiliser des requêtes SQL sur DataFrames enregistrées en tant que tables.

    sqlContext.registerDataFrameAsTable(data, "myTable")
    df2 = sqlContext.sql("SELECT Name AS name, askdaosdka as age from myTable")
    
    df2.show()
    
    # Output
    #+-------+---+
    #|   name|age|
    #+-------+---+
    #|Alberto|  2|
    #| Dakota|  2|
    #+-------+---+
    
207
Alberto Bonsanto
df = df.withColumnRenamed("colName", "newColName")
       .withColumnRenamed("colName2", "newColName2")

Avantage de cette manière: avec une longue liste de colonnes, vous ne souhaitez modifier que quelques noms de colonne Cela peut être très pratique dans ces scénarios. Très utile pour joindre des tables avec des noms de colonnes en double.

92
Pankaj Kumar

Si vous voulez changer tous les noms de colonnes, essayez df.toDF(*cols)

26
user8117731

Si vous souhaitez appliquer une transformation simple à tous les noms de colonne, ce code fait l'affaire: (je remplace tous les espaces par un trait de soulignement)

new_column_name_list= list(map(lambda x: x.replace(" ", "_"), df.columns))

df = df.toDF(*new_column_name_list)

Merci à @ user8117731 pour le tour toDf.

13
pbahr

Si vous souhaitez renommer une seule colonne et conserver le reste tel quel:

from pyspark.sql.functions import col
new_df = old_df.select(*[col(s).alias(new_name) if s == column_to_change else s for s in old_df.columns])
7
Ratul Ghosh

Une autre façon de renommer une seule colonne (en utilisant import pyspark.sql.functions as F):

df = df.select( '*', F.col('count').alias('new_count') ).drop('count')
3
scottlittle

J'ai créé une fonction facile à utiliser pour renommer plusieurs colonnes pour un dataframe pyspark, au cas où quelqu'un voudrait l'utiliser:

def renameCols(df, old_columns, new_columns):
    for old_col,new_col in Zip(old_columns,new_columns):
        df = df.withColumnRenamed(old_col,new_col)
    return df

old_columns = ['old_name1','old_name2']
new_columns = ['new_name1', 'new_name2']
df_renamed = renameCols(df, old_columns, new_columns)

Attention, les deux listes doivent être de la même longueur.

1
Manrique

J'utilise celui-ci:

from pyspark.sql.functions import col
df.select(['vin',col('timeStamp').alias('Date')]).show()
1
mike

c'est l'approche que j'ai utilisée:

créer une session pyspark:

import pyspark
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('changeColNames').getOrCreate()

créer un cadre de données:

df = spark.createDataFrame(data = [('Bob', 5.62,'juice'),  ('Sue',0.85,'milk')], schema = ["Name", "Amount","Item"])

voir df avec les noms de colonnes:

df.show()
+----+------+-----+
|Name|Amount| Item|
+----+------+-----+
| Bob|  5.62|juice|
| Sue|  0.85| milk|
+----+------+-----+

créer une liste avec de nouveaux noms de colonnes: 

newcolnames = ['NameNew','AmountNew','ItemNew']

changer les noms de colonne du df:

for c,n in Zip(df.columns,newcolnames):
    df=df.withColumnRenamed(c,n)

voir df avec les nouveaux noms de colonnes:

df.show()
+-------+---------+-------+
|NameNew|AmountNew|ItemNew|
+-------+---------+-------+
|    Bob|     5.62|  juice|
|    Sue|     0.85|   milk|
+-------+---------+-------+
0
Grant Shannon

Pour renommer une seule colonne, vous pouvez toujours utiliser toDF (). Par exemple,

df1.selectExpr("SALARY*2").toDF("REVISED_SALARY").show()
0
user24225