Ajouter la somme de la colonne comme nouvelle colonne dans le dataframe de PySpark

j'utilise PySpark et j'ai une base de données Spark avec un tas de colonnes numériques. Je veux ajouter une colonne qui est la somme de toutes les autres colonnes.

supposons que mon datagramme ait les colonnes "a", "b", et "c". Je sais que je peux faire ceci:

df.withColumn('total_col', df.a + df.b + df.c)

le problème est que je ne veux pas taper chaque colonne individuellement et les ajouter, surtout si j'ai beaucoup de colonnes. Je veux pouvoir le faire automatiquement ou en spécifiant une liste de noms de colonne que je veux ajouter. Est-il une autre façon de le faire?

16
demandé sur Paul 2015-08-12 05:59:12

2 réponses

Ce n'était pas évident. Je ne vois aucune somme par ligne des colonnes définies dans l'API spark Dataframes.

Version 2

Cela peut être fait d'une manière assez simple:

newdf = df.withColumn('total', sum(df[col] for col in df.columns))

df.columns est fourni par pyspark sous la forme d'une liste de chaînes donnant tous les noms de colonnes dans la base de données Spark. Pour une somme différente, vous pouvez fournir n'importe quelle autre liste de noms de colonne à la place.

Je n'ai pas essayé ceci comme première solution parce que je n'étais pas certain comment il serait comporter. Mais il fonctionne.

Version 1

C'est trop compliqué, mais fonctionne aussi bien.

Vous pouvez faire ceci:

  1. utiliser df.columns pour obtenir une liste des noms de colonnes
  2. utilisez cette liste de noms pour faire une liste des colonnes
  3. passer cette liste à quelque chose qui va invoquer la fonction add surchargée de la colonne dans un mode fonctionnel de type plie

avec python réduction, une certaine connaissance du fonctionnement de la surcharge de l'opérateur, et du code pyspark pour les colonnes ici devient:

def column_add(a,b):
     return  a.__add__(b)

newdf = df.withColumn('total_col', 
         reduce(column_add, ( df[col] for col in df.columns ) ))

notez qu'il s'agit d'une réduction python, pas d'une réduction RDD spark, et que le terme entre parenthèses du second paramètre à réduire nécessite la parenthèse car c'est une expression de générateur de liste.

Testé, Fonctionne!

$ pyspark
>>> df = sc.parallelize([{'a': 1, 'b':2, 'c':3}, {'a':8, 'b':5, 'c':6}, {'a':3, 'b':1, 'c':0}]).toDF().cache()
>>> df
DataFrame[a: bigint, b: bigint, c: bigint]
>>> df.columns
['a', 'b', 'c']
>>> def column_add(a,b):
...     return a.__add__(b)
...
>>> df.withColumn('total', reduce(column_add, ( df[col] for col in df.columns ) )).collect()
[Row(a=1, b=2, c=3, total=6), Row(a=8, b=5, c=6, total=19), Row(a=3, b=1, c=0, total=4)]
27
répondu Paul 2017-05-23 11:54:05

Mon problème était similaire à celle ci-dessus (peu plus complexe) que j'ai dû ajouter consécutive les colonnes totalisent les nouvelles colonnes de la dataframe de PySpark. Cette approche utilise un code de Paul Version 1 ci-dessus:

import pyspark
from pyspark.sql import SparkSession
import pandas as pd

spark = SparkSession.builder.appName('addColAsCumulativeSUM').getOrCreate()
df=spark.createDataFrame(data=[(1,2,3),(4,5,6),(3,2,1)\
                              ,(6,1,-4),(0,2,-2),(6,4,1)\
                              ,(4,5,2),(5,-3,-5),(6,4,-1)]\
                              ,schema=['x1','x2','x3'])
df.show()

+---+---+---+
| x1| x2| x3|
+---+---+---+
|  1|  2|  3|
|  4|  5|  6|
|  3|  2|  1|
|  6|  1| -4|
|  0|  2| -2|
|  6|  4|  1|
|  4|  5|  2|
|  5| -3| -5|
|  6|  4| -1|
+---+---+---+

colnames=df.columns

ajouter de nouvelles colonnes qui sont des sommes cumulées (consécutifs):

for i in range(0,len(colnames)):
    colnameLst= colnames[0:i+1]
    colname = 'cm'+ str(i+1)
    df = df.withColumn(colname, sum(df[col] for col in colnameLst))

df.show ()

+---+---+---+---+---+---+
| x1| x2| x3|cm1|cm2|cm3|
+---+---+---+---+---+---+
|  1|  2|  3|  1|  3|  6|
|  4|  5|  6|  4|  9| 15|
|  3|  2|  1|  3|  5|  6|
|  6|  1| -4|  6|  7|  3|
|  0|  2| -2|  0|  2|  0|
|  6|  4|  1|  6| 10| 11|
|  4|  5|  2|  4|  9| 11|
|  5| -3| -5|  5|  2| -3|
|  6|  4| -1|  6| 10|  9|
+---+---+---+---+---+---+

les colonnes "somme cumulative" ajoutées sont les suivantes:

cm1 = x1
cm2 = x1 + x2
cm3 = x1 + x2 + x3
0
répondu Grant Shannon 2018-07-04 14:56:20