Built with Tutify.io

    AIStudyLabs

    PySpark rank() Function with Examples

    PySpark rank() Function with Examples

    In PySpark, the rank() window function adds a new column by assigning a rank to each row within a partition of a dataset based on the specified order criteria. When multiple rows have the same value for the order column, they receive the same rank, but subsequent ranks are skipped. This function is especially useful in data analysis tasks such as identifying top performers within a group, filtering top-N records, or sorting data within subgroups.

    In this article, you’ll learn how to use the rank() function along with partitionBy() and orderBy() to group data and rank rows based on column values.

    Key Points-

    <a id="h-pyspark-rank-window-function"></a>

    PySpark rank Window Function

    The rank() function assigns a rank to each row within a certain partition based on the specified order.
    If rows with the same value in the ordering column, they receive the same rank, and skip the next rank.

    <a id="h-syntax-of-the-rank-function"></a>

    Syntax of the rank() Function

    The following is the syntax of the rank() function.

    
    # Syntax of the rank() function
    pyspark.sql.functions.rank()
    

    <a id="h-parameters"></a>

    Parameters

    <a id="h-return-value"></a>

    Return Value

    It returns a new column with ranks (IntegerType), where rows with the same value share the same rank, and skipped ranks occur when duplicates exist.

    <a id="h-pyspark-rank-partition-by"></a>

    PySpark rank Partition by

    You can use the rank() function to add a new column to DataFrame by defining a window with a partition and a specified order. It adds a rank number to each row. If some rows have the same value, they get the same rank, and the next rank numbers are skipped.

    
    # Add the rank to each row of a specified order within a partition
    # Create DataFrame
    # Imports
    from pyspark.sql import SparkSession
    from pyspark.sql.functions import row_number, rank, dense_rank, col
    from pyspark.sql.window import Window
    
    # Create SparkSession
    spark = SparkSession.builder.appName("aistudylabs").getOrCreate()
    
    # Sample data
    data = [
        ("James", "Sales", 3000),
        ("Michael", "Sales", 4600),
        ("Robert", "Sales", 4100),
        ("Maria", "Finance", 3000),
        ("Scott", "Finance", 3300),
        ("Jen", "Finance", 3900),
        ("Jeff", "Marketing", 3000),
        ("Kumar", "Marketing", 2000),
        ("Saif", "Sales", 4100)
    ]
    
    columns = ["employee_name", "department", "salary"]
    df = spark.createDataFrame(data, columns)
    df.show()
    
    window_spec = Window.partitionBy("department").orderBy(col("salary"))
    df.withColumn("rank", rank().over(window_spec)).show()
    

    Yields below the output.

    <a id="h-pyspark-rank-without-partition"></a>

    PySpark rank without Partition

    You can also use the rank() function to add a row number(rank) as a new column to a DataFrame without applying any partitioning. To do this by using the rank() function along with Window.orderBy()function, specifying only the ordering criteria. In this case, this function considers the entire DataFrame as a single group and adds row numbers based on the global order of the specified column.

    
    # Add the rank to each row without partition
    global_window = Window.orderBy(col("salary").desc())
    df.withColumn("rank", rank().over(global_window)).show()
    
    # Output:
    # +-------------+----------+------+----+
    # |employee_name|department|salary|rank|
    # +-------------+----------+------+----+
    # |      Michael|     Sales|  4600|   1|
    # |       Robert|     Sales|  4100|   2|
    # |         Saif|     Sales|  4100|   2|
    # |          Jen|   Finance|  3900|   4|
    # |        Scott|   Finance|  3300|   5|
    # |        James|     Sales|  3000|   6|
    # |        Maria|   Finance|  3000|   6|
    # |         Jeff| Marketing|  3000|   6|
    # |        Kumar| Marketing|  2000|   9|
    # +-------------+----------+------+----+
    

    <a id="h-pyspark-rank-order-by-desc"></a>

    PySpark rank Order by Desc

    To add ranks within each group based on descending order, you can use the rank() function along with a window specification.

    
    # Add the rank to each row within a partition by descending order 
    window_spec = Window.partitionBy("department").orderBy(col("salary").desc())
    df.withColumn("rank", rank().over(window_spec)).show()
    
    # Output:
    # +-------------+----------+------+----+
    # |employee_name|department|salary|rank|
    # +-------------+----------+------+----+
    # |          Jen|   Finance|  3900|   1|
    # |        Scott|   Finance|  3300|   2|
    # |        Maria|   Finance|  3000|   3|
    # |         Jeff| Marketing|  3000|   1|
    # |        Kumar| Marketing|  2000|   2|
    # |      Michael|     Sales|  4600|   1|
    # |       Robert|     Sales|  4100|   2|
    # |         Saif|     Sales|  4100|   2|
    # |        James|     Sales|  3000|   4|
    # +-------------+----------+------+----+
    

    <a id="h-pyspark-rank-vs-dense-rank"></a>

    PySpark rank vs dense_rank

    In this example, shows how these functions handle ranking when some rows have the same values.

    
    # Difference between PySpark rank() and dense_rank()
    window_spec = Window.partitionBy("department").orderBy(col("salary"))
    result_df = df.withColumn("rank", rank().over(window_spec)) \
                      .withColumn("dense_rank", dense_rank().over(window_spec))
    result_df.show()
    
    # Output:
    # +-------------+----------+------+----+----------+
    # |employee_name|department|salary|rank|dense_rank|
    # +-------------+----------+------+----+----------+
    # |        Maria|   Finance|  3000|   1|         1|
    # |        Scott|   Finance|  3300|   2|         2|
    # |          Jen|   Finance|  3900|   3|         3|
    # |        Kumar| Marketing|  2000|   1|         1|
    # |         Jeff| Marketing|  3000|   2|         2|
    # |        James|     Sales|  3000|   1|         1|
    # |       Robert|     Sales|  4100|   2|         2|
    # |         Saif|     Sales|  4100|   2|         2|
    # |      Michael|     Sales|  4600|   4|         3|
    # +-------------+----------+------+----+----------+
    

    <a id="h-pyspark-rank-vs-dense-rank-vs-row-number"></a>

    PySpark rank() vs dense_rank() vs row_number()

    This example shows the differences between the rank(), dense_rank(), and row_number() functionsin PySpark with a window partition. We’ll apply these functions to a DataFrame to add columns that represent row rankings based on the specified partition.

    
    # Complete example of Difference between PySpark rank(), dense_rank(),and row_number()
    # Applying partitionBy() and orderBy()
    window_spec = Window.partitionBy("department").orderBy(col("salary"))
    result_df = df.withColumn("row_number", row_number().over(window_spec))\
                      .withColumn("rank", rank().over(window_spec)) \
                      .withColumn("dense_rank", dense_rank().over(window_spec))
    
    # Show the result
    result_df.show()
    
    # Output:
    # +-------------+----------+------+----------+----+----------+
    # |employee_name|department|salary|row_number|rank|dense_rank|
    # +-------------+----------+------+----------+----+----------+
    # |        Maria|   Finance|  3000|         1|   1|         1|
    # |        Scott|   Finance|  3300|         2|   2|         2|
    # |          Jen|   Finance|  3900|         3|   3|         3|
    # |        Kumar| Marketing|  2000|         1|   1|         1|
    # |         Jeff| Marketing|  3000|         2|   2|         2|
    # |        James|     Sales|  3000|         1|   1|         1|
    # |       Robert|     Sales|  4100|         2|   2|         2|
    # |         Saif|     Sales|  4100|         3|   2|         2|
    # |      Michael|     Sales|  4600|         4|   4|         3|
    # +-------------+----------+------+----------+----+----------+
    

    <a id="h-frequently-asked-questions-of-pyspark-rank-function"></a>

    Frequently Asked Questions of PySpark rank() Function

    The rank() function assigns a ranking number to each row within a partition based on a specified order. Rows with the same value receive the same rank, and the next ranks are skipped.

    rank() gives the same rank to duplicate values and skips the next ranks.

    You can use rank() without partitionBy(). In that case, the entire DataFrame is treated as a single group.

    They receive the same rank, and the next rank(s) are skipped. For example, if two rows are tied at rank 1, the next rank will be 3.

    It returns a column of type IntegerType, representing the rank assigned to each row.

    You can use rank() with partitionBy() and orderBy(), then filter rows where rank is less than or equal to N.

    <a id="h-conclusion"></a>

    Conclusion

    In this article, I explained the rank() function and how to use it with a window specification to create a new column in a DataFrame. The function handles rows with identical values both with and without partitioning, based on the specified order. I also discussed the differences between rank(), dense_rank(), and row_number(), helping you choose the most suitable function for your specific data analysis needs.

    <a id="h-references"></a>

    References

    <a id="h-related-articles"></a>

    Related Articles