Wie füge ich einem Spark DataFrame eine neue Spalte hinzu (mit PySpark)?


127

Ich habe einen Spark DataFrame (mit PySpark 1.5.1) und möchte eine neue Spalte hinzufügen.

Ich habe Folgendes ohne Erfolg versucht:

type(randomed_hours) # => list

# Create in Python and transform to RDD

new_col = pd.DataFrame(randomed_hours, columns=['new_col'])

spark_new_col = sqlContext.createDataFrame(new_col)

my_df_spark.withColumn("hours", spark_new_col["new_col"])

Habe auch einen Fehler dabei:

my_df_spark.withColumn("hours",  sc.parallelize(randomed_hours))

Wie füge ich einem vorhandenen DataFrame mit PySpark eine neue Spalte (basierend auf dem Python-Vektor) hinzu?

Antworten:


206

Sie können einer DataFramein Spark keine beliebige Spalte hinzufügen . Neue Spalten können nur mithilfe von Literalen erstellt werden (andere Literaltypen werden unter Hinzufügen einer konstanten Spalte in einem Spark-Datenrahmen beschrieben? ).

from pyspark.sql.functions import lit

df = sqlContext.createDataFrame(
    [(1, "a", 23.0), (3, "B", -23.0)], ("x1", "x2", "x3"))

df_with_x4 = df.withColumn("x4", lit(0))
df_with_x4.show()

## +---+---+-----+---+
## | x1| x2|   x3| x4|
## +---+---+-----+---+
## |  1|  a| 23.0|  0|
## |  3|  B|-23.0|  0|
## +---+---+-----+---+

Transformieren einer vorhandenen Spalte:

from pyspark.sql.functions import exp

df_with_x5 = df_with_x4.withColumn("x5", exp("x3"))
df_with_x5.show()

## +---+---+-----+---+--------------------+
## | x1| x2|   x3| x4|                  x5|
## +---+---+-----+---+--------------------+
## |  1|  a| 23.0|  0| 9.744803446248903E9|
## |  3|  B|-23.0|  0|1.026187963170189...|
## +---+---+-----+---+--------------------+

enthalten mit join:

from pyspark.sql.functions import exp

lookup = sqlContext.createDataFrame([(1, "foo"), (2, "bar")], ("k", "v"))
df_with_x6 = (df_with_x5
    .join(lookup, col("x1") == col("k"), "leftouter")
    .drop("k")
    .withColumnRenamed("v", "x6"))

## +---+---+-----+---+--------------------+----+
## | x1| x2|   x3| x4|                  x5|  x6|
## +---+---+-----+---+--------------------+----+
## |  1|  a| 23.0|  0| 9.744803446248903E9| foo|
## |  3|  B|-23.0|  0|1.026187963170189...|null|
## +---+---+-----+---+--------------------+----+

oder generiert mit function / udf:

from pyspark.sql.functions import rand

df_with_x7 = df_with_x6.withColumn("x7", rand())
df_with_x7.show()

## +---+---+-----+---+--------------------+----+-------------------+
## | x1| x2|   x3| x4|                  x5|  x6|                 x7|
## +---+---+-----+---+--------------------+----+-------------------+
## |  1|  a| 23.0|  0| 9.744803446248903E9| foo|0.41930610446846617|
## |  3|  B|-23.0|  0|1.026187963170189...|null|0.37801881545497873|
## +---+---+-----+---+--------------------+----+-------------------+

In Bezug auf die Leistung werden integrierte Funktionen ( pyspark.sql.functions), die dem Catalyst-Ausdruck zugeordnet sind, normalerweise benutzerdefinierten Python-Funktionen vorgezogen.

Wenn Sie den Inhalt einer beliebigen RDD als Spalte hinzufügen möchten, können Sie dies tun


1
"Neue Spalten können nur mit Literalen erstellt werden" Was genau bedeuten Literale in diesem Zusammenhang?
Timbram

Die Dokumentation von Spark ist großartig, siehe df.withColumn spark.apache.org/docs/2.1.0/api/python/…
Steven Black

10
Die Spark-Dokumentation ist nur insofern "großartig", als sie eine große Menge an Nutzungsmöglichkeiten für den klugen Leser einer Übung überlässt. Spark (und Pyspark) decken einen wahren Zoo von Datenstrukturen ab, mit wenig oder keiner Anleitung zum Konvertieren zwischen ihnen. Ein typisches Beispiel: Verbreitung von Fragen wie dieser.
Shadowtalker

62

So fügen Sie eine Spalte mithilfe einer UDF hinzu:

df = sqlContext.createDataFrame(
    [(1, "a", 23.0), (3, "B", -23.0)], ("x1", "x2", "x3"))

from pyspark.sql.functions import udf
from pyspark.sql.types import *

def valueToCategory(value):
   if   value == 1: return 'cat1'
   elif value == 2: return 'cat2'
   ...
   else: return 'n/a'

# NOTE: it seems that calls to udf() must be after SparkContext() is called
udfValueToCategory = udf(valueToCategory, StringType())
df_with_cat = df.withColumn("category", udfValueToCategory("x1"))
df_with_cat.show()

## +---+---+-----+---------+
## | x1| x2|   x3| category|
## +---+---+-----+---------+
## |  1|  a| 23.0|     cat1|
## |  3|  B|-23.0|      n/a|
## +---+---+-----+---------+

30

Für Spark 2.0

# assumes schema has 'age' column 
df.select('*', (df.age + 10).alias('agePlusTen'))

1
Muss df.select sein ('*', (df.age + 10) .alias ('agePlusTen'))
Frank B.

1
Vielen Dank, und wenn Sie eingeben df = df.select('*', (df.age + 10).alias('agePlusTen')), fügen Sie effektiv eine beliebige Spalte hinzu, da @ zero323 uns oben gewarnt hat, dass dies unmöglich ist, es sei denn, es stimmt etwas nicht in Spark, in Pandas ist dies der Standardweg.
Kardamom

Gibt es eine Version davon für pySpark?
Tagar

@Tagar Über dem Snippet befindet sich Python.
Luke W

1
@ GeoffreyAnderson,df.select('*', df.age + 10, df.age + 20)
Mark Rajcok

2

Es gibt mehrere Möglichkeiten, eine neue Spalte in pySpark hinzuzufügen.

Erstellen wir zunächst einen einfachen DataFrame.

date = [27, 28, 29, None, 30, 31]
df = spark.createDataFrame(date, IntegerType())

Versuchen wir nun, den Spaltenwert zu verdoppeln und in einer neuen Spalte zu speichern. PFB wenige verschiedene Ansätze, um das gleiche zu erreichen.

# Approach - 1 : using withColumn function
df.withColumn("double", df.value * 2).show()

# Approach - 2 : using select with alias function.
df.select("*", (df.value * 2).alias("double")).show()

# Approach - 3 : using selectExpr function with as clause.
df.selectExpr("*", "value * 2 as double").show()

# Approach - 4 : Using as clause in SQL statement.
df.createTempView("temp")
spark.sql("select *, value * 2 as double from temp").show()

Weitere Beispiele und Erklärungen zu den Funktionen von spark DataFrame finden Sie in meinem Blog .

Ich hoffe das hilft.


0

Sie können eine neue definieren, udfwenn Sie Folgendes hinzufügen column_name:

u_f = F.udf(lambda :yourstring,StringType())
a.select(u_f().alias('column_name')

0
from pyspark.sql.functions import udf
from pyspark.sql.types import *
func_name = udf(
    lambda val: val, # do sth to val
    StringType()
)
df.withColumn('new_col', func_name(df.old_col))

Sie müssen anrufen StringType().
Gberger

0

Ich möchte ein allgemeines Beispiel für einen sehr ähnlichen Anwendungsfall anbieten:

Anwendungsfall: Ich habe eine CSV bestehend aus:

First|Third|Fifth
data|data|data
data|data|data
...billion more lines

Ich muss einige Transformationen durchführen und die endgültige CSV muss so aussehen

First|Second|Third|Fourth|Fifth
data|null|data|null|data
data|null|data|null|data
...billion more lines

Ich muss dies tun, da dies das von einem Modell definierte Schema ist und meine endgültigen Daten mit SQL Bulk Inserts und dergleichen interoperabel sein müssen.

so:

1) Ich habe die Original-CSV mit spark.read gelesen und nenne sie "df".

2) Ich mache etwas mit den Daten.

3) Ich füge die Nullspalten mit diesem Skript hinzu:

outcols = []
for column in MY_COLUMN_LIST:
    if column in df.columns:
        outcols.append(column)
    else:
        outcols.append(lit(None).cast(StringType()).alias('{0}'.format(column)))

df = df.select(outcols)

Auf diese Weise können Sie Ihr Schema nach dem Laden einer CSV strukturieren (würde auch zum Neuordnen von Spalten funktionieren, wenn Sie dies für viele Tabellen tun müssen).


0

Der einfachste Weg, eine Spalte hinzuzufügen, ist die Verwendung von "withColumn". Da der Datenrahmen mit sqlContext erstellt wird, müssen Sie das Schema angeben oder es kann standardmäßig im Dataset verfügbar sein. Wenn das Schema angegeben wird, wird die Arbeitslast bei jeder Änderung mühsam.

Unten finden Sie ein Beispiel, das Sie berücksichtigen können:

from pyspark.sql import SQLContext
from pyspark.sql.types import *
sqlContext = SQLContext(sc) # SparkContext will be sc by default 

# Read the dataset of your choice (Already loaded with schema)
Data = sqlContext.read.csv("/path", header = True/False, schema = "infer", sep = "delimiter")

# For instance the data has 30 columns from col1, col2, ... col30. If you want to add a 31st column, you can do so by the following:
Data = Data.withColumn("col31", "Code goes here")

# Check the change 
Data.printSchema()

0

Mit den folgenden Schritten können wir DataFrame direkt zusätzliche Spalten hinzufügen:

from pyspark.sql.functions import when
df = spark.createDataFrame([["amit", 30], ["rohit", 45], ["sameer", 50]], ["name", "age"])
df = df.withColumn("profile", when(df.age >= 40, "Senior").otherwise("Executive"))
df.show()
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.