J'ai trois tableaux de type chaîne contenant les informations suivantes:
J'essaie d'utiliser des trames de données d'allumage pour y parvenir. Les cadres de données Spark fournissent un agg () où vous pouvez passer une entrée Map [String, String] (avec le nom de la colonne et l'opération d'agrégation respective), mais je souhaite effectuer différentes opérations d'agrégation sur la même colonne de données. Des suggestions sur la façon de réaliser ceci?
Scala :
Vous pouvez par exemple mapper une liste de fonctions avec une mapping
définie de nom en fonction:
import org.Apache.spark.sql.functions.{col, min, max, mean}
import org.Apache.spark.sql.Column
val df = Seq((1L, 3.0), (1L, 3.0), (2L, -5.0)).toDF("k", "v")
val mapping: Map[String, Column => Column] = Map(
"min" -> min, "max" -> max, "mean" -> avg)
val groupBy = Seq("k")
val aggregate = Seq("v")
val operations = Seq("min", "max", "mean")
val exprs = aggregate.flatMap(c => operations .map(f => mapping(f)(col(c))))
df.groupBy(groupBy.map(col): _*).agg(exprs.head, exprs.tail: _*).show
// +---+------+------+------+
// | k|min(v)|max(v)|avg(v)|
// +---+------+------+------+
// | 1| 3.0| 3.0| 3.0|
// | 2| -5.0| -5.0| -5.0|
// +---+------+------+------+
ou
df.groupBy(groupBy.head, groupBy.tail: _*).agg(exprs.head, exprs.tail: _*).show
Malheureusement, l'analyseur utilisé en interne SQLContext
n'est pas exposé publiquement, mais vous pouvez toujours essayer de construire des requêtes SQL en clair:
df.registerTempTable("df")
val groupExprs = groupBy.mkString(",")
val aggExprs = aggregate.flatMap(c => operations.map(
f => s"$f($c) AS ${c}_${f}")
).mkString(",")
sqlContext.sql(s"SELECT $groupExprs, $aggExprs FROM df GROUP BY $groupExprs")
Python :
from pyspark.sql.functions import mean, sum, max, col
df = sc.parallelize([(1, 3.0), (1, 3.0), (2, -5.0)]).toDF(["k", "v"])
groupBy = ["k"]
aggregate = ["v"]
funs = [mean, sum, max]
exprs = [f(col(c)) for f in funs for c in aggregate]
# or equivalent df.groupby(groupBy).agg(*exprs)
df.groupby(*groupBy).agg(*exprs)
Pour ceux qui se demandent, comment @ zero323 peut être écrit sans compréhension de liste en python:
from pyspark.sql.functions import min, max, col
# init your spark dataframe
expr = [min(col("valueName")),max(col("valueName"))]
df.groupBy("keyName").agg(*expr)