Во-первых, группа по годам и месяцам.Мы можем считать нули и ненулевые значения на группу в каждом столбце и суммировать их после преобразования в целые числа;эта часть довольно проста.
Для подсчета элементов, которые появляются в одном столбце, но не в другом, мы можем использовать collect_set
, который объединяет уникальные элементы в один массив вместе с array_except
:
from pyspark.sql import functions as F
from pyspark.sql.types import IntegerType
result = (df
.groupBy(F.year('date').alias('year'), F.month('date').alias('month'))
.agg(F.sum(F.isnull('x').cast(IntegerType())).alias('x_null'),
F.sum(F.isnull('y').cast(IntegerType())).alias('y_null'),
F.sum((~F.isnull('x')).cast(IntegerType())).alias('x_not_null'),
F.sum((~F.isnull('y')).cast(IntegerType())).alias('y_not_null'),
F.collect_set('x').alias('x_unique'),
F.collect_set('y').alias('y_unique'))
.withColumn('x_not_in_y_count', F.size(F.array_except('x_unique', 'y_unique')))
.withColumn('y_not_in_x_count', F.size(F.array_except('y_unique', 'x_unique')))
.drop('x_unique', 'y_unique')
.orderBy('year', 'month')
)
Учитывая следующие тестовые данные:
+----------+----+----+
| date| x| y|
+----------+----+----+
|1991-01-01|null| 2|
|1991-01-02| 1|null|
|1991-01-03| 2| 3|
|1991-02-01|null| 1|
|1991-02-02|null| 2|
+----------+----+----+
Это вывод:
+----+-----+------+------+----------+----------+----------------+----------------+
|year|month|x_null|y_null|x_not_null|y_not_null|x_not_in_y_count|y_not_in_x_count|
+----+-----+------+------+----------+----------+----------------+----------------+
|1991| 1| 1| 1| 2| 2| 1| 1|
|1991| 2| 2| 0| 0| 2| 0| 2|
+----+-----+------+------+----------+----------+----------------+----------------+