Comment sélectionner la première ligne de chaque groupe?
J'ai un DataFrame généré comme suit:
df.groupBy($"Hour", $"Category")
.agg(sum($"value") as "TotalValue")
.sort($"Hour".asc, $"TotalValue".desc))
Les résultats ressemblent à:
+----+--------+----------+
|Hour|Category|TotalValue|
+----+--------+----------+
| 0| cat26| 30.9|
| 0| cat13| 22.1|
| 0| cat95| 19.6|
| 0| cat105| 1.3|
| 1| cat67| 28.5|
| 1| cat4| 26.8|
| 1| cat13| 12.6|
| 1| cat23| 5.3|
| 2| cat56| 39.6|
| 2| cat40| 29.7|
| 2| cat187| 27.9|
| 2| cat68| 9.8|
| 3| cat8| 35.6|
| ...| ....| ....|
+----+--------+----------+
Comme vous pouvez le voir, le DataFrame est commandé par Hour
dans un ordre croissant, puis par TotalValue
dans un ordre décroissant.
Je voudrais sélectionner la ligne supérieure de chaque groupe, c'est à dire
- du groupe de l'Heure==0 sélectionnez (0,cat26,de 30,9)
- du groupe de l'Heure==1 sélectionnez (1,cat67,28.5)
- du groupe de l'Heure==2 sélectionnez (2,cat56,de 39,6)
- et ainsi de suite
De sorte que la sortie désirée serait:
+----+--------+----------+
|Hour|Category|TotalValue|
+----+--------+----------+
| 0| cat26| 30.9|
| 1| cat67| 28.5|
| 2| cat56| 39.6|
| 3| cat8| 35.6|
| ...| ...| ...|
+----+--------+----------+
Il pourrait être pratique de pouvoir sélectionner les N premières lignes de chaque groupe ainsi.
Toute aide est très appréciée.
OriginalL'auteur Rami | 2015-11-23
Vous devez vous connecter pour publier un commentaire.
Fonctions de la fenêtre de:
Quelque chose comme cela devrait faire l'affaire:
Cette méthode sera inefficace en cas de données significatives de l'inclinaison.
Plaine d'agrégation SQL suivie par
join
:Sinon, vous pouvez rejoindre des données agrégées cadre:
Il va garder les valeurs en double (si il n'y a plus d'une catégorie à l'heure, avec le même total de la valeur). Vous pouvez supprimer ces comme suit:
À l'aide de la commande de plus de
structs
:Soigné, bien que pas très bien testé, le truc qui ne nécessite pas de jointures ou les fonctions de la fenêtre:
Avec DataSet API (Étincelle de 1,6+, 2.0+):
Étincelle de 1,6:
Spark 2.0 ou version ultérieure:
Les deux dernières méthodes peuvent tirer parti de la carte côté de combiner et de ne pas exiger de plein droit la lecture aléatoire de sorte que la plupart du temps, ils présentent une meilleure performance par rapport à des fonctions de la fenêtre et des jointures. Ces canne être également utilisé avec des Streaming en
completed
mode de sortie.Ne pas utiliser:
Il peut sembler pour le travail (notamment dans le
local
mode), mais il n'est pas fiable (SPARK-16207). Les crédits à Tzach Zohar pour la liaison pertinentes JIRA problème.La même remarque s'applique à
qui utilise en interne équivalent du plan d'exécution.
Sur le Ne pas utiliser de df.orderBy(...).gropBy(...). Dans quelles circonstances peut-on compter sur orderBy(...)? ou si nous ne pouvons pas être sûr si orderBy() va donner le résultat correct, quelles alternatives avons-nous?
J'ai peut-être oublié quelque chose, mais en général, il est recommandé de éviter groupByKey, au lieu reduceByKey doit être utilisé. Aussi, vous économiserez une seule ligne.
en évitant groupBy/groupByKey est seulement lorsque vous traitez avec des Rdd, vous remarquerez que le jeu de données de l'api n'a même pas un reduceByKey fonction.
href="https://stackoverflow.com/q/32902982/8371915">DataFrame / Dataset groupBy comportement/optimisation
OriginalL'auteur zero323
Pour Spark 2.0.2 avec le groupement de plusieurs colonnes:
OriginalL'auteur Antonín Hoskovec
C'est exactement la même de zero323's réponse mais dans la requête SQL.
En supposant que dataframe est créé et enregistré comme
Fonction de fenêtre :
Plaine d'agrégation SQL suivie par rejoindre:
À l'aide de la commande de plus de structs:
Ensembles de données de manière et ne pas faires sont les mêmes que dans l'original de la réplique
OriginalL'auteur Ramesh Maharjan
La solution ci-dessous ne fait qu'une groupBy et d'en extraire les lignes de votre dataframe qui contiennent le maxValue d'un seul coup. Pas besoin de plus de Jointures ou Windows.
vous avez un groupe de la première place, qui déclenche un shuffle. C'est pas pire que la fonction "fenêtre ouverte" parce que dans une fonction de fenêtre, il va évaluer la fenêtre pour chaque ligne unique dans le dataframe.
OriginalL'auteur elghoto
Si le dataframe doit être regroupés en plusieurs colonnes, ce qui peut aider
Espère que cela aide quelqu'un avec le même problème
OriginalL'auteur NehaM
Une belle façon de le faire avec le dataframe api utilise le argmax logique comme
OriginalL'auteur randal25
Le modèle est
groupe par des touches => faire quelque chose pour chaque groupe, par exemple, de réduire => retour à dataframe
Je pensais que le Dataframe l'abstraction est un peu lourd, dans ce cas, j'ai donc utilisé RDD fonctionnalité
OriginalL'auteur Rubber Duck
Ici, vous pouvez faire comme ceci -
OriginalL'auteur Shubham Agrawal
On peut utiliser le rang() de la fenêtre de fonction (lorsque vous choisissez le rang = 1)
rang ajoute juste un numéro pour chaque ligne d'un groupe (dans ce cas, il serait l'heure)
voici un exemple. ( à partir de https://github.com/jaceklaskowski/mastering-apache-spark-book/blob/master/spark-sql-functions.adoc#rank )
OriginalL'auteur Vasile Surdu