web-dev-qa-db-fra.com

Comment remplacer toute la colonne existante dans Spark dataframe avec une nouvelle colonne?

Je veux écraser une colonne spark avec une nouvelle colonne qui est un drapeau binaire.

J'ai essayé d'écraser directement la colonne id2, mais pourquoi cela ne fonctionne-t-il pas comme une opération sur place dans Pandas?

Comment le faire sans utiliser withcolumn () pour créer une nouvelle colonne et drop () pour supprimer l'ancienne colonne?

Je sais que spark dataframe est immuable, est-ce la raison ou il existe une manière différente d'écraser sans utiliser withcolumn () & drop ()?

    df2 = spark.createDataFrame(
        [(1, 1, float('nan')), (1, 2, float(5)), (1, 3, float('nan')), (1, 4, float('nan')), (1, 5, float(10)), (1, 6, float('nan')), (1, 6, float('nan'))],
        ('session', "timestamp1", "id2"))

    df2.select(df2.id2 > 0).show()

+---------+
|(id2 > 0)|
+---------+
|     true|
|     true|
|     true|
|     true|
|     true|
|     true|
|     true|
+---------+
 # Attempting to overwriting df2.id2
    df2.id2=df2.select(df2.id2 > 0).withColumnRenamed('(id2 > 0)','id2')
    df2.show()
#Overwriting unsucessful
+-------+----------+----+
|session|timestamp1| id2|
+-------+----------+----+
|      1|         1| NaN|
|      1|         2| 5.0|
|      1|         3| NaN|
|      1|         4| NaN|
|      1|         5|10.0|
|      1|         6| NaN|
|      1|         6| NaN|
+-------+----------+----+
7
GeorgeOfTheRF

Vous pouvez utiliser

d1.withColumnRenamed("colName", "newColName")
d1.withColumn("newColName", $"colName")

withColumnRenamed renomme la colonne existante en nouveau nom.

withColumn crée une nouvelle colonne avec un nom donné. Il crée une nouvelle colonne avec le même nom s'il existe déjà et supprime l'ancienne.

Dans votre cas, il ne change pas dans le dataframe original df2 il change le nom de la colonne et retourne comme un nouveau dataframe qui devrait être assigné à une nouvelle variable pour une utilisation ultérieure.

d3 = df2.select((df2.id2 > 0).alias("id2")

Ci-dessus devrait bien fonctionner dans votre cas.

J'espère que cela t'aides!

13
koiralo

Comme indiqué ci-dessus, il n'est pas possible de remplacer l'objet DataFrame, qui est une collection immuable, de sorte que toutes les transformations renvoient un nouveau DataFrame.

Le moyen le plus rapide d'obtenir l'effet souhaité est d'utiliser withColumn:

df = df.withColumn("col", some expression)

col est le nom de la colonne que vous souhaitez "remplacer". Après avoir exécuté cette valeur de la variable df sera remplacée par le nouveau DataFrame avec la nouvelle valeur de la colonne col. Vous voudrez peut-être l'assigner à une nouvelle variable.

Dans votre cas, il peut ressembler à:

df2 = df2.withColumn("id2", (df2.id2 > 0) & (df2.id2 != float('nan')))

J'ai ajouté la comparaison à nan, car je suppose que vous ne voulez pas traiter nan comme supérieur à 0.

3
Piotr Kalański

Si vous travaillez avec plusieurs colonnes du même nom dans différentes tables jointes, vous pouvez utiliser l'alias de table dans colName dans withColumn.

Par exemple. df1.join(df2, df1.id = df2.other_id).withColumn('df1.my_col', F.greatest(df1.my_col, df2.my_col))

Et si vous souhaitez uniquement conserver les colonnes de df1, vous pouvez également appeler .select('df1.*')

Si vous faites plutôt df1.join(df2, df1.id = df2.other_id).withColumn('my_col', F.greatest(df1.my_col, df2.my_col))

Je pense qu'il écrase la dernière colonne qui s'appelle my_col. Il génère donc: id, my_col (df1.my_col original value), id, other_id, my_col (newly computed my_col)

1
Trang Pham