orderBy如何影响Pyspark数据框架中的Window.partitionBy?

orderBy如何影响Pyspark数据框架中的Window.partitionBy?,pyspark,window,sql-order-by,Pyspark,Window,Sql Order By,我通过一个例子来解释我的问题: 假设我们有一个数据帧,如下所示: original_df = sc.createDataFrame([('x', 10,), ('x', 15,), ('x', 10,), ('x', 25,), ('y', 20,), ('y', 10,), ('y', 20,)], ["key", "price"] ) original_df.show() 输出: +---+-----+ |key|price| +---+-----+ | x| 10| | x|

我通过一个例子来解释我的问题:
假设我们有一个数据帧,如下所示:

original_df = sc.createDataFrame([('x', 10,), ('x', 15,), ('x', 10,), ('x', 25,), ('y', 20,), ('y', 10,), ('y', 20,)], ["key", "price"] )
original_df.show()
输出:

+---+-----+
|key|price|
+---+-----+
|  x|   10|
|  x|   15|
|  x|   10|
|  x|   25|
|  y|   20|
|  y|   10|
|  y|   20|
+---+-----+
+---+-----+----------------+
|key|price|      price_list|
+---+-----+----------------+
|  x|   10|[10, 15, 10, 25]|
|  x|   15|[10, 15, 10, 25]|
|  x|   10|[10, 15, 10, 25]|
|  x|   25|[10, 15, 10, 25]|
|  y|   20|    [20, 10, 20]|
|  y|   10|    [20, 10, 20]|
|  y|   20|    [20, 10, 20]|
+---+-----+----------------+
+---+-----+----------------+
|key|price|    ordered_list|
+---+-----+----------------+
|  x|   10|        [10, 10]|
|  x|   10|        [10, 10]|
|  x|   15|    [10, 10, 15]|
|  x|   25|[10, 10, 15, 25]|
|  y|   10|            [10]|
|  y|   20|    [10, 20, 20]|
|  y|   20|    [10, 20, 20]|
+---+-----+----------------+
假设我想使用
窗口获得每个
键的
价格列表

w = Window.partitionBy('key')
original_df.withColumn('price_list', F.collect_list('price').over(w)).show()
输出:

+---+-----+
|key|price|
+---+-----+
|  x|   10|
|  x|   15|
|  x|   10|
|  x|   25|
|  y|   20|
|  y|   10|
|  y|   20|
+---+-----+
+---+-----+----------------+
|key|price|      price_list|
+---+-----+----------------+
|  x|   10|[10, 15, 10, 25]|
|  x|   15|[10, 15, 10, 25]|
|  x|   10|[10, 15, 10, 25]|
|  x|   25|[10, 15, 10, 25]|
|  y|   20|    [20, 10, 20]|
|  y|   10|    [20, 10, 20]|
|  y|   20|    [20, 10, 20]|
+---+-----+----------------+
+---+-----+----------------+
|key|price|    ordered_list|
+---+-----+----------------+
|  x|   10|        [10, 10]|
|  x|   10|        [10, 10]|
|  x|   15|    [10, 10, 15]|
|  x|   25|[10, 10, 15, 25]|
|  y|   10|            [10]|
|  y|   20|    [10, 20, 20]|
|  y|   20|    [10, 20, 20]|
+---+-----+----------------+
到目前为止还不错。
但如果我想获得一个有序列表,并将
orderBy
添加到我的窗口
w
中,我会得到:

w = Window.partitionBy('key').orderBy('price')
original_df.withColumn('ordered_list', F.collect_list('price').over(w)).show()
输出:

+---+-----+
|key|price|
+---+-----+
|  x|   10|
|  x|   15|
|  x|   10|
|  x|   25|
|  y|   20|
|  y|   10|
|  y|   20|
+---+-----+
+---+-----+----------------+
|key|price|      price_list|
+---+-----+----------------+
|  x|   10|[10, 15, 10, 25]|
|  x|   15|[10, 15, 10, 25]|
|  x|   10|[10, 15, 10, 25]|
|  x|   25|[10, 15, 10, 25]|
|  y|   20|    [20, 10, 20]|
|  y|   10|    [20, 10, 20]|
|  y|   20|    [20, 10, 20]|
+---+-----+----------------+
+---+-----+----------------+
|key|price|    ordered_list|
+---+-----+----------------+
|  x|   10|        [10, 10]|
|  x|   10|        [10, 10]|
|  x|   15|    [10, 10, 15]|
|  x|   25|[10, 10, 15, 25]|
|  y|   10|            [10]|
|  y|   20|    [10, 20, 20]|
|  y|   20|    [10, 20, 20]|
+---+-----+----------------+
这意味着,
orderBy
(某种程度上)也更改了窗口中的行(与
rowsBetween
所做的相同)!这是不应该的

即使我可以通过在窗口中指定
rowsBetween
来修复它,并获得预期的结果

w = Window.partitionBy('key').orderBy('price').rowsBetween(Window.unboundedPreceding, Window.unboundedFollowing)

有人能解释一下为什么
orderBy
会以这种方式影响
窗口吗?

Spark窗口使用三个部分指定:分区、顺序和框架

  • 如果未指定任何部分,则整个数据集将被视为单个窗口
  • 当使用列指定分区时,将为列的每个不同值创建一个窗口。如果只指定了分区,那么当为一行计算WHE时,将考虑该分区中的所有行。这就是为什么您可以看到分区x中所有行的所有4个值[10,15,10,25]
  • 如果指定了分区和排序,则在计算行函数时,它将采用分区中行的秩顺序,并包括具有相同或更低值(如果指定了默认asc顺序)秩的所有行。在您的例子中,第一行包括[10,10],因为分区中有两行具有相同的秩
  • 当指定了帧规范rowsbeween和rangeBetween时,行求值将仅拾取与帧规则匹配的行。e、 g.如果指定了unbounded和currentRow,则它将拾取当前行及其之前出现的所有行。如果指定了orderBy,它将相应地更改在当前行之前出现的行
  • 特别是针对您的问题,orderBy不仅用于对分区数据进行排序,还可以更改行帧选择

    下面是不同的windowspec和相应的输出

    Window.orderBy()
    +---+-----+----------------------------+
    |key|price|price_list                  |
    +---+-----+----------------------------+
    |x  |15   |[15, 10, 10, 20, 10, 25, 20]|
    |x  |10   |[15, 10, 10, 20, 10, 25, 20]|
    |y  |10   |[15, 10, 10, 20, 10, 25, 20]|
    |y  |20   |[15, 10, 10, 20, 10, 25, 20]|
    |x  |10   |[15, 10, 10, 20, 10, 25, 20]|
    |x  |25   |[15, 10, 10, 20, 10, 25, 20]|
    |y  |20   |[15, 10, 10, 20, 10, 25, 20]|
    +---+-----+----------------------------+
    
    Window.partitionBy('key')
    +---+-----+----------------+
    |key|price|      price_list|
    +---+-----+----------------+
    |  x|   15|[15, 10, 10, 25]|
    |  x|   10|[15, 10, 10, 25]|
    |  x|   10|[15, 10, 10, 25]|
    |  x|   25|[15, 10, 10, 25]|
    |  y|   20|    [20, 10, 20]|
    |  y|   10|    [20, 10, 20]|
    |  y|   20|    [20, 10, 20]|
    +---+-----+----------------+
    
    Window.partitionBy('key').orderBy('price')
    +---+-----+----------------+
    |key|price|    ordered_list|
    +---+-----+----------------+
    |  x|   10|        [10, 10]|
    |  x|   10|        [10, 10]|
    |  x|   15|    [10, 10, 15]|
    |  x|   25|[10, 10, 15, 25]|
    |  y|   10|            [10]|
    |  y|   20|    [10, 20, 20]|
    |  y|   20|    [10, 20, 20]|
    +---+-----+----------------+
    
    w = Window.partitionBy('key').orderBy(F.desc('price'))
    +---+-----+----------------+
    |key|price|    ordered_list|
    +---+-----+----------------+
    |  x|   25|            [25]|
    |  x|   15|        [25, 15]|
    |  x|   10|[25, 15, 10, 10]|
    |  x|   10|[25, 15, 10, 10]|
    |  y|   20|        [20, 20]|
    |  y|   20|        [20, 20]|
    |  y|   10|    [20, 20, 10]|
    +---+-----+----------------+
    
    Window.partitionBy('key').orderBy('price').rowsBetween(Window.unboundedPreceding, Window.currentRow)
    +---+-----+----------------+
    |key|price|    ordered_list|
    +---+-----+----------------+
    |  x|   10|            [10]|
    |  x|   10|        [10, 10]|
    |  x|   15|    [10, 10, 15]|
    |  x|   25|[10, 10, 15, 25]|
    |  y|   10|            [10]|
    |  y|   20|        [10, 20]|
    |  y|   20|    [10, 20, 20]|
    +---+-----+----------------+
    
    Window.partitionBy('key').rowsBetween(Window.unboundedPreceding, Window.currentRow)
    +---+-----+----------------+
    |key|price|    ordered_list|
    +---+-----+----------------+
    |  x|   15|            [15]|
    |  x|   10|        [15, 10]|
    |  x|   10|    [15, 10, 10]|
    |  x|   25|[15, 10, 10, 25]|
    |  y|   10|            [10]|
    |  y|   20|        [10, 20]|
    |  y|   20|    [10, 20, 20]|
    +---+-----+----------------+
    

    @ManojSingh的答案是完美的。我仍然想分享我的观点,以便我能有所帮助

    窗口.partitionBy('key')
    对于数据帧中的每个不同的
    都像一个
    groupBy
    一样工作,允许您对所有键执行相同的操作

    当在可排序列中执行时,
    orderBy
    通常是有意义的。例如,一个名为
    'month'
    的列包含一年中的所有月份(1,2,3…12),另一个名为
    'price'
    的列包含每个月的价格。如果您想计算每个月和之前所有月份的总和、平均值或其他值,可以使用
    orderBy
    。例如,这对于计算月份之间的变化是很好的