web-dev-qa-db-fra.com

Comment ajouter une nouvelle colonne à un Spark DataFrame (en utilisant PySpark)?

J'ai un Spark DataFrame (utilisant PySpark 1.5.1) et j'aimerais ajouter une nouvelle colonne.

J'ai essayé ce qui suit sans aucun succès:

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"])

Aussi eu une erreur en utilisant ceci:

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

Alors, comment puis-je ajouter une nouvelle colonne (basée sur le vecteur Python) à un DataFrame existant avec PySpark?

105
Boris

Vous ne pouvez pas ajouter une colonne arbitraire à un DataFrame dans Spark. Les nouvelles colonnes ne peuvent être créées qu’en utilisant des littéraux (d’autres types de littéraux sont décrits dans Comment ajouter une colonne constante dans un Spark DataFrame? )

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

transformer une colonne existante:

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...|
## +---+---+-----+---+--------------------+

inclus avec 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|
## +---+---+-----+---+--------------------+----+

ou généré avec la fonction/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|
## +---+---+-----+---+--------------------+----+-------------------+

Les fonctions intégrées relatives aux performances (pyspark.sql.functions), qui mappent à l'expression Catalyst, sont généralement préférées aux fonctions Python définies par l'utilisateur.

Si vous souhaitez ajouter le contenu d’un RDD arbitraire sous forme de colonne, vous pouvez

165
zero323

Pour ajouter une colonne à l'aide d'un fichier UDF:

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|
## +---+---+-----+---------+
53
Mark Rajcok

Pour Spark 2.

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

J'aimerais proposer un exemple généralisé pour un cas d'utilisation très similaire:

Cas d'utilisation: j'ai un csv composé de:

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

Je dois effectuer certaines transformations et le fichier CSV final doit ressembler à

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

Je dois le faire car il s’agit du schéma défini par un modèle et j’ai besoin de l’interopérabilité de mes données finales avec les insertions en bloc SQL et autres.

alors:

1) J'ai lu le csv original en utilisant spark.read et je l'ai appelé "df".

2) Je fais quelque chose aux données.

3) J'ajoute les colonnes nulles à l'aide de ce script:

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)

De cette façon, vous pouvez structurer votre schéma après avoir chargé un csv (fonctionnerait également pour réorganiser les colonnes si vous devez le faire pour plusieurs tables).

0
bloodrootfc

Nous pouvons ajouter des colonnes supplémentaires à DataFrame directement en procédant comme suit:

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()
0
yogesh

Le moyen le plus simple d’ajouter une colonne est d’utiliser "withColumn". Le cadre de données étant créé à l'aide de sqlContext, vous devez spécifier le schéma ou, par défaut, il peut être disponible dans l'ensemble de données. Si le schéma est spécifié, la charge de travail devient fastidieuse à chaque modification.

Voici un exemple que vous pouvez considérer:

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