Как orderBy влияет на Window.partitionBy в фрейме данных Pyspark? - PullRequest
0 голосов
/ 06 декабря 2018

Я объясняю свой вопрос на примере:
Допустим, у нас есть следующий кадр данных:

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|
+---+-----+

И предположим, что я хочу получитьсписок prices для каждого key с использованием window:

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

Вывод:

+---+-----+----------------+
|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]|
+---+-----+----------------+

Пока все хорошо.
Но если я хочу получитьупорядоченный список, и я добавляю orderBy в свое окно w Я получаю:

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

Вывод:

+---+-----+----------------+
|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 влияет на window таким образом?

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Ответ @ManojSingh идеален.Я все еще хочу поделиться своей точкой зрения, чтобы я мог быть полезным.

Window.partitionBy('key') работает как groupBy для каждого отдельного key в кадре данных, позволяя вам выполнять одну и ту же операциюнад всеми из них.

orderBy обычно имеет смысл, когда он выполняется в сортируемой колонке.Возьмем, к примеру, столбец с именем 'month', содержащий все месяцы в году (1,2,3 ... 12), и еще один с именем 'price' с ценой за каждый месяц.Если вы хотите получить сумму, среднее значение или что-то еще для каждого месяца и всех предыдущих, используйте orderBy.Это хорошо, например, для расчета разницы между месяцами.

0 голосов
/ 06 декабря 2018

Spark Window задаются с использованием трех частей: раздела, порядка и рамки.

  1. Если ни одна из частей не указана, то весь набор данных будет рассматриваться как одно окно.
  2. Когда разделение указывается с использованием столбца, одно окно на отдельное значение столбца имеет видсоздано.Если указан только раздел, то при оценке строки для всех учитываются все строки в этом разделе.Вот почему вы видите все 4 значения [10, 15, 10, 25] для всех строк в разделе x.
  3. Если задано разделение и упорядочение, то при оценке функции строки она принимает порядок ранга строкв раздел и все строки, которые имеют одинаковое или более низкое значение (если задан порядок asc по умолчанию), включены в рангВ вашем случае первая строка включает в себя [10,10], потому что в разделе 2 строки с одинаковым рангом.
  4. Если указаны спецификации Frame rowBetween и rangeBetween, то при оценке строки будут выбраны только те строки, которые соответствуют кадруправить.например, unbounded и currentRow указан, он выберет текущую строку и все строки, которые появляются перед ней.Если указан параметр orderBy, он изменит соответствующие строки перед текущей строкой.

специально для вашего вопроса, orderBy предназначен не только для сортировки разделенных данных, но и для изменения выбора кадра строки

Ниже приведены различные спецификации окон и соответствующие выходные данные

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]|
+---+-----+----------------+
...