Группировка значений, которые являются последовательностью в два столбца pyspark

У меня есть следующий ДФ:

index      initial_range      final_range
1            1000000              5999999
2            6000000              6299999
3            6300000              6399999
4            6400000              6499999
5            6600000              6699999
6            6700000              6749999
7            6750000              6799999
8            7000000              7399999
9            7600000              7699999
10           7700000              7749999
11           7750000              7799999
12           6500000              6549999

Обратите внимание, что поля «initial_range» и «final_range» представляют собой интервалы нечеткости. Когда мы сравниваем индекс строки 1 и индекс 2, мы видим, что конец значения поля «final_range» начинается в следующем как последовательность + 1 в индексе «initial_range» 2. Таким образом, в примере, заканчивающемся на 5999999 и началось с 6000000 в индексе 2. Мне нужно сгруппировать эти случаи и вернуть следующий df:

index      initial_range      final_range       grouping
1            1000000              5999999    1000000-6549999
2            6000000              6299999    1000000-6549999
3            6300000              6399999    1000000-6549999
4            6400000              6499999    1000000-6549999
5            6600000              6699999    6600000-6799999
6            6700000              6749999    6600000-6799999
7            6750000              6799999    6600000-6799999
8            7000000              7399999    7000000-7399999
9            7600000              7699999    7600000-7799999
10           7700000              7749999    7600000-7799999
11           7750000              7799999    7600000-7799999
12           6500000              6549999    1000000-6549999

Видите, что в поле группировки есть новостные аранжировки, то есть значения min(начальное) и max(конечное), пока последовательность не нарушена.

Некоторые детали:

  • Индекс 4 для 5 последовательности + 1 нарушен, поэтому новая «группировка» меняется. Другими словами, каждый раз, когда последовательность нарушается, необходимо писать новую последовательность.
  • В индексе 12 снова появляется группа 1000000-6549999, потому что 6500000 является следующим числом 6499999 в индексе 4.

Я пробовал этот код:

comparison = df == df.shift()+1
df['grouping'] = comparison['initial_range'] & comparison['final_range']

Но логическая последовательность не сработала.

Может кто-нибудь мне помочь?

кто-нибудь, чтобы помочь мне?

Vivian 09.02.2023 21:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, это было сложно, вот мой ответ,

Прежде всего, я использую UDF, поэтому ожидайте, что производительность будет немного хуже,

import copy
import pyspark.sql.functions as F
from pyspark.sql.types import *

rn = 0

def check_vals(x, y):
    global rn
    
    if (y != None) and (int(x)+1) == int(y):
        return rn + 1
    else:
        # Using copy to deepcopy and not forming a shallow one.
        res = copy.copy(rn)
        # Increment so that the next value with start form +1
        rn += 1
        # Return the same value as we want to group using this
        return res + 1
    
    return 0

rn_udf = F.udf(lambda x, y: check_vals(x, y), IntegerType())

Следующий,

from pyspark.sql.window import Window

# We want to check the final_range values according to the initial_value 
w = Window().orderBy(F.col('initial_range'))

# First of all take the next row values of initial range in a column called nextRange so that we can compare
# Check if the final_range+1 == nextRange, if yes use rn value, if not then use rn and increment it for the next iteration.
# Now find the max and min values in the partition created by the check_1 column.
# Concat min and max values
# order it by ID to get the initial ordering, I have to cast it to integer but you might not need it
# drop all calculated values
df.withColumn('nextRange', F.lead('initial_range').over(w)) \
    .withColumn('check_1', rn_udf("final_range", "nextRange")) \
    .withColumn('min_val', F.min("initial_range").over(Window.partitionBy("check_1"))) \
    .withColumn('max_val', F.max("final_range").over(Window.partitionBy("check_1"))) \
    .withColumn('range', F.concat("min_val", F.lit("-"), "max_val")) \
    .orderBy(F.col("ID").cast(IntegerType())) \
    .drop("nextRange", "check_1", "min_val", "max_val") \
    .show(truncate=False)

Выход:

+---+-------------+-----------+---------------+
|ID |initial_range|final_range|range          |
+---+-------------+-----------+---------------+
|1  |1000000      |5999999    |1000000-6549999|
|2  |6000000      |6299999    |1000000-6549999|
|3  |6300000      |6399999    |1000000-6549999|
|4  |6400000      |6499999    |1000000-6549999|
|5  |6600000      |6699999    |6600000-6799999|
|6  |6700000      |6749999    |6600000-6799999|
|7  |6750000      |6799999    |6600000-6799999|
|8  |7000000      |7399999    |7000000-7399999|
|9  |7600000      |7699999    |7600000-7799999|
|10 |7700000      |7749999    |7600000-7799999|
|11 |7750000      |7799999    |7600000-7799999|
|12 |6500000      |6549999    |1000000-6549999|
+---+-------------+-----------+---------------+

очень хороший! Это сработало, но я забыл, что данные нужно группировать. Итак, в поле id в вашем выводе повторить. Пример: 7 первых строк были ID = 1, в других словах мы применяем группу, следуя той же логике. Можете ли вы помочь мне в этом datail?

Vivian 10.02.2023 14:34

В каждой группе применяется одна и та же логика. Было ясно?

Vivian 10.02.2023 14:35

В столбце check_1 я создаю значения для группировки. Вы можете использовать show, чтобы проверить

Tushar Patil 13.02.2023 06:25

Другие вопросы по теме