web-dev-qa-db-de.com

Wie man Dataframe-Spaltennamen in Pyspark ändert?

Ich komme aus Pandas Hintergrund und bin es gewohnt, Daten aus CSV-Dateien in einen Datenrahmen zu lesen und dann die Spaltennamen einfach mit dem einfachen Befehl in etwas Nützliches zu ändern:

df.columns = new_column_name_list

Das Gleiche funktioniert jedoch nicht in Pyspark-Datenrahmen, die mit sqlContext erstellt wurden. Die einzige Lösung, die ich finden könnte, ist die folgende:

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)

Dabei wird die Variable im Wesentlichen zweimal definiert, und das Schema wird zuerst abgeleitet. Anschließend werden die Spaltennamen umbenannt und der Datenrahmen mit dem aktualisierten Schema erneut geladen. 

Gibt es einen besseren und effizienteren Weg, wie bei Pandas?

Meine Spark-Version ist 1.5.0

95

Dafür gibt es viele Möglichkeiten: 

  • Option 1. Verwenden Sie 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. Beachten Sie mit withColumnRenamed , dass Sie mit dieser Methode die gleiche Spalte "überschreiben" können.

    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 , in Scala können Sie auch as verwenden.

    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. Verwenden Sie sqlContext.sql , wodurch Sie SQL-Abfragen für DataFrames verwenden können, die als Tabellen registriert sind.

    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
df = df.withColumnRenamed("colName", "newColName")
       .withColumnRenamed("colName2", "newColName2")

Vorteil dieser Vorgehensweise: Bei einer langen Spaltenliste möchten Sie nur wenige Spaltennamen ändern. Dies kann in diesen Szenarien sehr praktisch sein. Sehr nützlich, wenn Sie Tabellen mit doppelten Spaltennamen verbinden.

92
Pankaj Kumar

Wenn Sie alle Spaltennamen ändern möchten, versuchen Sie df.toDF(*cols).

26
user8117731

Falls Sie eine einfache Transformation auf alle Spaltennamen anwenden möchten, führt dieser Code den Trick aus: (Ich ersetze alle Leerzeichen durch Unterstrich)

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

df = df.toDF(*new_column_name_list)

Danke an @ user8117731 für den toDf-Trick.

13
pbahr

df.withColumnRenamed('age', 'age2')

8

Wenn Sie eine einzelne Spalte umbenennen möchten und den Rest unverändert lassen:

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

Eine andere Möglichkeit, nur eine Spalte umzubenennen (mit import pyspark.sql.functions as F):

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

Ich habe eine einfach zu verwendende Funktion erstellt, um mehrere Spalten für einen Pyspark-Datenrahmen umzubenennen, falls jemand sie verwenden möchte:

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)

Achtung, beide Listen müssen gleich lang sein.

1
Manrique

Ich benutze dieses:

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

dies ist der Ansatz, den ich verwendet habe:

pyspark-Session erstellen:

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

datenrahmen erstellen:

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

ansicht df mit Spaltennamen:

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

erstellen Sie eine Liste mit neuen Spaltennamen: 

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

Ändern Sie die Spaltennamen der Datenbank:

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

ansicht df mit neuen Spaltennamen:

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

Für die Umbenennung einer einzelnen Spalte können Sie weiterhin toDF () verwenden. Zum Beispiel,

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