web-dev-qa-db-fra.com

Spark DataFrame: compte les valeurs distinctes de chaque colonne

La question est à peu près dans le titre: Existe-t-il un moyen efficace de compter les valeurs distinctes dans chaque colonne d'un DataFrame?

La méthode décrire fournit uniquement le nombre, mais pas le nombre distinct, et je me demande s’il existe un moyen d’obtenir le nombre distinct pour toutes les colonnes (ou certaines colonnes sélectionnées).

20
Rami

Les agrégations multiples seraient assez coûteuses à calculer. Je vous suggère d'utiliser des méthodes d'approximation à la place. Dans ce cas, en comptant approximativement le compte distinct:

val df = Seq((1,3,4),(1,2,3),(2,3,4),(2,3,5)).toDF("col1","col2","col3")

val exprs = df.columns.map((_ -> "approx_count_distinct")).toMap
df.agg(exprs).show()
// +---------------------------+---------------------------+---------------------------+
// |approx_count_distinct(col1)|approx_count_distinct(col2)|approx_count_distinct(col3)|
// +---------------------------+---------------------------+---------------------------+
// |                          2|                          2|                          3|
// +---------------------------+---------------------------+---------------------------+

La méthode approx_count_distinct Repose sur HyperLogLog sous le capot.

L'algorithme HyperLogLog et sa variante HyperLogLog ++ (implémentée dans Spark) s'appuient sur l'observation suivante astucieuse.

Si les nombres sont répartis uniformément sur une plage, le nombre d'éléments distincts peut être approximé à partir du plus grand nombre de zéros au début de la représentation binaire des nombres.

Par exemple, si nous observons un nombre dont les chiffres sous forme binaire sont de la forme 0…(k times)…01…1, alors nous pouvons estimer qu'il y a dans l'ordre de 2 ^ k éléments dans l'ensemble. C'est une estimation très grossière, mais elle peut être affinée avec une grande précision grâce à un algorithme d'esquisse.

Une explication détaillée de la mécanique derrière cet algorithme peut être trouvée dans le article original .

Remarque: Démarrer Spark 1.6 , lorsque Spark appelle SELECT SOME_AGG(DISTINCT foo)), SOME_AGG(DISTINCT bar)) FROM df chaque clause doit déclencher une agrégation distincte pour chaque clause, alors que ceci est différent de SELECT SOME_AGG(foo), SOME_AGG(bar) FROM df où nous agrégons une fois. Par conséquent, les performances ne sont pas comparables lorsque vous utilisez un count(distinct(_)) et approxCountDistinct (ou approx_count_distinct).

C'est un des changements de comportement depuis Spark 1.6:

Grâce au planificateur de requêtes amélioré pour les requêtes ayant des agrégations distinctes (SPARK-9241), le plan d'une requête comportant une seule agrégation distincte a été remplacé par une version plus robuste. Pour revenir au plan généré par Spark 1.5), définissez spark.sql.specializeSingleDistinctAggPlanning sur true. (SPARK-12077)

Référence: Algorithmes approximatifs dans Apache Spark: HyperLogLog et Quantiles .

30
eliasah

Dans pySpark, vous pouvez faire quelque chose comme ceci en utilisant countDistinct():

from pyspark.sql.functions import col, countDistinct

df.agg(*(countDistinct(col(c)).alias(c) for c in df.columns))

De même dans Scala:

import org.Apache.spark.sql.functions.countDistinct
import org.Apache.spark.sql.functions.col

df.select(df.columns.map(c => countDistinct(col(c)).alias(c)): _*)

Si vous voulez accélérer les choses en cas de perte potentielle de précision, vous pouvez également utiliser approxCountDistinct().

33
mtoto

si vous voulez juste compter pour une colonne particulière, suivez les conseils suivants. Bien que sa réponse tardive. cela pourrait aider quelqu'un. (pyspark 2.2.0 testé)

from pyspark.sql.functions import col, countDistinct
df.agg(countDistinct(col("colName")).alias("count")).show()
9
desaiankitb

En ajoutant à la réponse de desaiankitb, ceci vous fournirait une réponse plus intuitive:

de pyspark.sql.functions nombre d'import

df.groupBy(colname).count().show()
2
thegooner

Vous pouvez utiliser la fonction count(column name) de SQL

Alternativement, si vous utilisez l'analyse de données et que vous voulez une estimation approximative et non un compte exact de chaque colonne, vous pouvez utiliser la fonction approx_count_distinct approx_count_distinct(expr[, relativeSD])

0
Ahmed