web-dev-qa-db-fra.com

Spark SQL Row_number () PartitionBy Sort Desc

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?

18
jKraut

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"))
36
zero323

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()
1
kennyut

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.