Правило заключается в следующем.
Найдите перекрытие последовательно обрабатывать даты между последующими строками.
Я уже пронумеровал строки для упорядочивания.
Шаги:
- Если Process_start_date предыдущей строки равна =process_start_date следующей строки
Я успешно выполнил кодирование до этого шага. Но следующий шаг правила довольно сложен.
Если две строки перекрываются, возьмите наименьшую (начальную дату) и наибольшую (конечную дату) из двух перекрывающихся строк и сравните ее с третья строка, если шаги 1 и 2 для этого сравнения верны, тогда строка 3 становится частью перекрывающейся группы вместе со строками 1 и 2, и мы берем наименьшую и наибольшую даты из 3 строк и сравниваем с четвертой строкой.
Этот процесс продолжается для раздела идентификатора клиента и идентификатора местоположения, как показано в коде ниже.
Если строки I и 2 не перекрываются, сравнение переходит к строкам. 2 и 3 и выполните те же действия.
Внутри раздела может быть несколько отдельных перекрывающихся групп, поэтому вполне возможно, что строки 1 и 2 представляют собой одну группу, а строки 3 и 4 – другую группу. и строки 5,6 не являются частью группу.
Для строк 5 и 6 они могут либо входить во вторую группу, либо не входить ни в одну группу, поскольку это последовательное сравнение.
Результат, который мне нужен, должен быть примерно таким
+--------+----------+----------+------------------+----------------+-------------+
|recordno|customerid|locationid|process_start_date|process_end_date|overlap_group|
+--------+----------+----------+------------------+----------------+-------------+
| 1| 2277953| A| 2015-03-13| 2016-04-15| 1|
| 2| 2277953| A| 2016-04-04| 2019-12-31| 1|
| 3| 2277953| A| 2019-06-06| 2019-06-20| 1|
| 4| 2277953| A| 2019-06-30| 2019-12-31| 1|
| 5| 2277953| A| 2020-01-01| 2020-12-31| 2|
| 6| 2277953| A| 2020-06-30| 2020-12-31| 2|
+--------+----------+----------+------------------+----------------+-------------+
Согласно моей логике, строка 4 должна быть частью группы 1, но она отображается как разгруппированный как 2.
Мой код выглядит следующим образом
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, lag, when, sum as spark_sum
from pyspark.sql.window import Window
# Initialize Spark session
spark = SparkSession.builder.appName("OptimizedOverlapGrouping").getOrCreate()
# Sample data
data = [
(1, 2277953, 'A', '2015-03-13', '2016-04-15'),
(2, 2277953, 'A', '2016-04-04', '2019-12-31'),
(3, 2277953, 'A', '2019-06-06', '2019-06-20'),
(4, 2277953, 'A', '2019-06-30', '2019-12-31'),
(5, 2277953, 'A', '2020-01-01', '2020-12-31'),
(6, 2277953, 'A', '2020-06-30', '2020-12-31')
]
# Create DataFrame
df = spark.createDataFrame(data, ['recordno', 'customerid', 'locationid', 'process_start_date', 'process_end_date'])
df = df.withColumn("process_start_date", col("process_start_date").cast("date"))
df = df.withColumn("process_end_date", col("process_end_date").cast("date"))
# Step 1: Define window for partitioning by group and ordering by start date
window_spec = Window.partitionBy("customerid", "locationid").orderBy("process_start_date")
# Step 2: Compare each row with the previous row to detect non-overlapping groups
df_with_lag = df.withColumn(
"prev_EndDate", lag("process_end_date").over(window_spec)
)
# Step 3: Identify the start of a new overlap group
df_with_group_flag = df_with_lag.withColumn(
"is_new_group",
when(
(col("prev_EndDate").isNull()) | (col("process_start_date") > col("prev_EndDate")),
1
).otherwise(0)
)
# Step 4: Generate sequential group numbers for overlapping records
df_with_overlap_group = df_with_group_flag.withColumn(
"overlap_group",
spark_sum("is_new_group").over(window_spec)
).drop("prev_EndDate", "is_new_group")
df_with_overlap_group.show()
Подробнее здесь: https://stackoverflow.com/questions/793 ... ark-python
Мобильная версия