J'ai un dataframe Spark avec plusieurs colonnes. Je veux ajouter une colonne à la structure de données qui représente la somme d'un certain nombre de colonnes.
Par exemple, mes données ressemblent à ceci:
ID var1 var2 var3 var4 var5
a 5 7 9 12 13
b 6 4 3 20 17
c 4 9 4 6 9
d 1 2 6 8 1
Je veux une colonne ajoutée qui résume les lignes pour des colonnes spécifiques:
ID var1 var2 var3 var4 var5 sums
a 5 7 9 12 13 46
b 6 4 3 20 17 50
c 4 9 4 6 9 32
d 1 2 6 8 10 27
Je sais qu'il est possible d'ajouter des colonnes si vous connaissez les colonnes spécifiques à ajouter:
val newdf = df.withColumn("sumofcolumns", df("var1") + df("var2"))
Mais est-il possible de passer une liste de noms de colonnes et de les additionner? Basé sur cette réponse, qui est fondamentalement ce que je veux mais utilise l’API de Python au lieu de scala ( Ajouter la somme des colonnes comme nouvelle colonne dans PySpark dataframe )
//Select columns to sum
val columnstosum = ("var1", "var2","var3","var4","var5")
// Create new column called sumofcolumns which is sum of all columns listed in columnstosum
val newdf = df.withColumn("sumofcolumns", df.select(columstosum.head, columnstosum.tail: _*).sum)
La valeur d'erreur sum n'est pas membre d'org.Apache.spark.sql.DataFrame. Y a-t-il un moyen de faire la somme sur les colonnes?
Merci d'avance pour votre aide.
Vous devriez essayer ce qui suit:
import org.Apache.spark.sql.functions._
val sc: SparkContext = ...
val sqlContext = new SQLContext(sc)
import sqlContext.implicits._
val input = sc.parallelize(Seq(
("a", 5, 7, 9, 12, 13),
("b", 6, 4, 3, 20, 17),
("c", 4, 9, 4, 6 , 9),
("d", 1, 2, 6, 8 , 1)
)).toDF("ID", "var1", "var2", "var3", "var4", "var5")
val columnsToSum = List(col("var1"), col("var2"), col("var3"), col("var4"), col("var5"))
val output = input.withColumn("sums", columnsToSum.reduce(_ + _))
output.show()
Alors le résultat est:
+---+----+----+----+----+----+----+
| ID|var1|var2|var3|var4|var5|sums|
+---+----+----+----+----+----+----+
| a| 5| 7| 9| 12| 13| 46|
| b| 6| 4| 3| 20| 17| 50|
| c| 4| 9| 4| 6| 9| 32|
| d| 1| 2| 6| 8| 1| 18|
+---+----+----+----+----+----+----+
Clair et simple:
import org.Apache.spark.sql.Column
import org.Apache.spark.sql.functions.{lit, col}
def sum_(cols: Column*) = cols.foldLeft(lit(0))(_ + _)
val columnstosum = Seq("var1", "var2", "var3", "var4", "var5").map(col _)
df.select(sum_(columnstosum: _*))
avec équivalent Python:
from functools import reduce
from operator import add
from pyspark.sql.functions import lit, col
def sum_(*cols):
return reduce(add, cols, lit(0))
columnstosum = [col(x) for x in ["var1", "var2", "var3", "var4", "var5"]]
select("*", sum_(*columnstosum))
La valeur par défaut est NA si une valeur est manquante dans la ligne. Vous pouvez utiliser la fonction DataFrameNaFunctions.fill
ou coalesce
pour éviter cela.
Je suppose que vous avez une df dataframe. Ensuite, vous pouvez résumer tous les cols à l'exception de votre col d'identité. Ceci est utile lorsque vous avez plusieurs colonnes et que vous ne voulez pas mentionner manuellement les noms de toutes les colonnes, comme toutes les colonnes mentionnées ci-dessus. Ce post a la même réponse.
val sumAll = df.columns.collect{ case x if x != "ID" => col(x) }.reduce(_ + _)
df.withColumn("sum", sumAll)
Voici une solution élégante utilisant python:
NewDF = OldDF.withColumn('sums', sum(OldDF[col] for col in OldDF.columns[1:]))
Espérons que cela va influencer quelque chose de similaire dans Spark ... ça vous tente?.