Пивот данных в PySpark
Преобразование длинного формата в широкий через groupBy().pivot().agg(), указание списка значений, несколько агрегаций, подводные камни и лучшие практики.
Пивот — это операция преобразования данных, при которой строки превращаются в колонки: «длинный» формат становится «широким». В PySpark это выполняется цепочкой .groupBy() + .pivot() + агрегация.
Синтаксис¶
pivot_df = df.groupBy("grouping_column") \
.pivot("pivot_column", values=[...optional list...]) \
.agg({"agg_column": "agg_function"})
grouping_column: колонка(и) для группировкиpivot_column: колонка, чьи уникальные значения станут новыми колонкамиvalues: необязательный список значений в pivot-колонке для ограничения вывода (иначе Spark определяет уникальные значения самостоятельно)agg_column / agg_function: колонка для агрегации и функция агрегации (sum, avg, count и др.)
Пример: базовый пивот¶
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("PySpark Pivot Example") \
.getOrCreate()
data = [
("A", "East", 100),
("A", "West", 150),
("B", "East", 200),
("B", "West", 250),
("C", "East", 300),
("C", "West", 350)
]
columns = ["Product", "Region", "Sales"]
df = spark.createDataFrame(data, columns)
df.show()
Вывод:
+-------+------+-----+
|Product|Region|Sales|
+-------+------+-----+
| A| East| 100|
| A| West| 150|
| B| East| 200|
| B| West| 250|
| C| East| 300|
| C| West| 350|
+-------+------+-----+
Теперь выполним пивот по Region, группируя по Product и агрегируя sum(Sales):
pivot_df = df.groupBy("Product") \
.pivot("Region") \
.sum("Sales")
pivot_df.show()
Ожидаемый результат:
+-------+----+----+
|Product|East|West|
+-------+----+----+
| A| 100| 150|
| B| 200| 250|
| C| 300| 350|
+-------+----+----+
Каждый регион становится колонкой, а значения — суммой продаж.
Указание списка значений¶
Если в pivot-колонке много уникальных значений, но нужна только часть из них, используйте параметр values=:
pivot_df2 = df.groupBy("Product") \
.pivot("Region", ["East"]) \
.sum("Sales")
pivot_df2.show()
В результате будет только колонка "East" (без "West"). Удобно для контроля ширины выходного DataFrame.
Несколько агрегаций¶
from pyspark.sql.functions import sum, avg
agg_df = df.groupBy("Product") \
.pivot("Region") \
.agg(
sum("Sales").alias("total_sales"),
avg("Sales").alias("avg_sales")
)
agg_df.show()
В результате получится по две колонки на каждый регион (например, East_total_sales, East_avg_sales, West_total_sales, West_avg_sales).
Применение и лучшие практики¶
Когда использовать пивот:
- Когда нужно создать перекрёстные таблицы (например, итоги по категориям в разрезе групп)
- Когда требуется широкий формат для отчётности или передачи в другие инструменты
На что обращать внимание:
- Если в pivot-колонке много уникальных значений, результирующий DataFrame станет очень широким — это может вызвать проблемы с памятью и производительностью
- Параметр
values=помогает избежать избыточной ширины вывода - NULL-значения: если для конкретной комбинации pivot-значения и группы данных нет, в этой колонке будет
null— обрабатывайте через.fillna(0) - Пивот вызывает перемешивание данных (shuffle); при работе с большими наборами данных планируйте партиционирование и ресурсы