J'ai réussi à créer une row_number()
partitionBy
par dans Spark en utilisant Windows, mais je voudrais trier cela par ordre décroissant, au lieu de l'ascendant par défaut. Ici est mon code de travail:
from pyspark import HiveContext
from pyspark.sql.types import *
from pyspark.sql import Row, functions as F
from pyspark.sql.window import Window
data_cooccur.select("driver", "also_item", "unit_count",
F.rowNumber().over(Window.partitionBy("driver").orderBy("unit_count")).alias("rowNum")).show()
Cela me donne ce résultat:
+------+---------+----------+------+
|driver|also_item|unit_count|rowNum|
+------+---------+----------+------+
| s10| s11| 1| 1|
| s10| s13| 1| 2|
| s10| s17| 1| 3|
Et ici j'ajoute le desc () pour l'ordre décroissant:
data_cooccur.select("driver", "also_item", "unit_count", F.rowNumber().over(Window.partitionBy("driver").orderBy("unit_count").desc()).alias("rowNum")).show()
Et obtenez cette erreur:
AttributeError: l'objet 'WindowSpec' n'a pas d'attribut 'desc'
Qu'est-ce que je fais mal ici?
desc
doit être appliqué sur une colonne et non sur une définition de fenêtre. Vous pouvez utiliser une méthode sur une colonne:
from pyspark.sql.functions import col
F.rowNumber().over(Window.partitionBy("driver").orderBy(col("unit_count").desc())
ou une fonction autonome:
from pyspark.sql.functions import desc
F.rowNumber().over(Window.partitionBy("driver").orderBy(desc("unit_count"))
Ou vous pouvez utiliser le code SQL dans Spark-SQL:
from pyspark.sql import SparkSession
spark = SparkSession\
.builder\
.master('local[*]')\
.appName('Test')\
.getOrCreate()
spark.sql("""
select driver
,also_item
,unit_count
,ROW_NUMBER() OVER (PARTITION BY driver ORDER BY unit_count DESC) AS rowNum
from data_cooccur
""").show()
Mise à jour En fait, j'ai essayé d'en savoir plus, et cela semble ne pas fonctionner. (en fait, il lance une erreur). La raison pour laquelle cela n'a pas fonctionné est que j'avais ce code sous un appel à display()
dans Databricks (le code après l'appel display()
n'est jamais exécuté). Il semble que la orderBy()
sur une trame de données et la orderBy()
sur une window
ne soient pas réellement les mêmes. Je garderai cette réponse juste pour confirmation négative
Depuis PySpark 2.4, (et probablement plus tôt), l'ajout simple du mot clé ascending=False
Dans l'appel orderBy
fonctionne pour moi.
Ex.
personal_recos.withColumn("row_number", F.row_number().over(Window.partitionBy("COLLECTOR_NUMBER").orderBy("count", ascending=False)))
et
personal_recos.withColumn("row_number", F.row_number().over(Window.partitionBy("COLLECTOR_NUMBER").orderBy(F.col("count").desc())))
semblent me donner le même comportement.