Пометьте последующие строки после изменения значения в одном столбце, если это основано на условии в столбце B.

Вопрос или проблема

У меня есть проблема с следующими данными:

месяц продукт версия цена категория
1 A alpha 500 foo
2 A alpha 500 foo
3 A alpha 550 foo
4 A alpha 600 bar
5 A alpha 500 bar
6 A alpha 500 faz
7 A alpha 500 faz
8 A alpha 500 faz
9 A alpha 500 faz
10 A alpha 500 foo
4 A beta 700 bar
5 A beta 800 bar
6 A beta 800 faz
7 A beta 800 faz
8 A beta 800 faz
9 A beta 700 faz
10 A beta 500 foo
1 B alpha 200 foo
2 B alpha 200 foo
3 B alpha 250 foo
4 B alpha 250 bar
5 B alpha 250 bar
6 B alpha 250 faz
7 B alpha 250 faz
8 B alpha 250 faz
9 B alpha 500 faz
10 B alpha 500 foo
4 B beta 700 bar
5 B beta 800 bar
6 B beta 800 faz
7 B beta 800 faz
8 B beta 800 faz
9 B beta 700 faz
10 B beta 500 foo

Что я хотел бы сделать, так это сгруппировать по продуктах и версиям, и отметить строки, где цена остается неизменной, НО категория меняется с предыдущего месяца для каждой группы продукт+версия. Кроме того, я хочу отметить все строки после первого изменения категории, где цена соответствует последней строке предыдущей категории.

Я пробовал подходы в SQL с LEAD и LAG, а также CASE WHEN exists, но не смог получить логику, которая работала бы так, как нужно. Мои подходы смогли отметить один следующий месяц, но не несколько месяцев после изменения категории.

Я также открыт к реализации решения на Python.

Столбец меток ниже представляет желаемый вывод.

месяц продукт версия цена категория метка
1 A alpha 500 foo OK
2 A alpha 500 foo OK
3 A alpha 550 foo OK
4 A alpha 600 bar OK
5 A alpha 500 bar OK
6 A alpha 500 faz FLAG
7 A alpha 500 faz FLAG
8 A alpha 500 faz FLAG
9 A alpha 500 faz FLAG
10 A alpha 500 foo FLAG
4 A beta 700 bar OK
5 A beta 800 bar OK
6 A beta 800 faz FLAG
7 A beta 800 faz FLAG
8 A beta 800 faz FLAG
9 A beta 700 faz OK
10 A beta 500 foo OK
1 B alpha 200 foo OK
2 B alpha 200 foo OK
3 B alpha 250 foo OK
4 B alpha 250 bar FLAG
5 B alpha 250 bar FLAG
6 B alpha 250 faz FLAG
7 B alpha 250 faz FLAG
8 B alpha 250 faz FLAG
9 B alpha 500 faz OK
10 B alpha 500 foo OK
4 B beta 700 bar OK
5 B beta 800 bar OK
6 B beta 800 faz FLAG
7 B beta 800 faz FLAG
8 B beta 800 faz FLAG
9 B beta 700 faz OK
10 B beta 500 foo OK

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

WITH cte AS ( SELECT , ROW_NUMBER() OVER (PARTITION BY product, version ORDER BY month ASC) AS rn FROM table ), 
flux AS ( SELECT c., CASE WHEN EXISTS( SELECT 1 FROM cte c2 WHERE (c.product = c2.product AND c.version = c2.version) AND c2.rn < c.rn AND c2.price BETWEEN -1000 AND 1000 AND c.category != c2.category ) THEN 1 ELSE 0 END AS tag FROM cte c ORDER BY month ) 
SELECT * FROM flux

Ответ или решение

Для решения вашей задачи можно использовать Python с библиотекой pandas, что является гибким и мощным инструментом для обработки данных. Ниже я приведу детальный шаг за шагом метод, который поможет вам добавить столбец с тегами в ваш набор данных в зависимости от условия изменения категории при неизменной цене.

Шаг 1: Подготовка данных

Прежде всего, вам необходимо импортировать необходимые библиотеки и создать DataFrame из ваших данных:

import pandas as pd

data = {
    'month': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
              4, 5, 6, 7, 8, 9, 10,
              1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
              4, 5, 6, 7, 8, 9, 10],
    'product': ['A']*10 + ['A']*7 + ['B']*10 + ['B']*7,
    'version': ['alpha']*10 + ['beta']*7 + ['alpha']*10 + ['beta']*7,
    'price': [500, 500, 550, 600, 500, 500, 500, 500, 500, 500,
              700, 800, 800, 800, 800, 700, 500,
              200, 200, 250, 250, 250, 250, 250, 250, 250, 500,
              700, 800, 800, 800, 800, 700, 500],
    'category': ['foo', 'foo', 'foo', 'bar', 'bar', 'faz', 'faz', 'faz', 'faz', 'foo',
                 'bar', 'bar', 'faz', 'faz', 'faz', 'faz', 'foo',
                 'foo', 'foo', 'foo', 'bar', 'bar', 'faz', 'faz', 'faz', 'faz', 'faz', 'foo',
                 'bar', 'bar', 'faz', 'faz', 'faz', 'faz', 'foo']
}

df = pd.DataFrame(data)

Шаг 2: Логика тегирования

Теперь мы реализуем логику для тегирования:

# Добавляем столбец "tag" с предначальным значением "OK"
df['tag'] = 'OK'

# Определяем функцию для применения логики тегирования
def tag_rows(group):
    # Сохраняем предыдущее значение цены и категории
    prev_price = None
    prev_category = None

    for index, row in group.iterrows():
        if (prev_price is not None and 
            row['price'] == prev_price and 
            row['category'] != prev_category):
            # Если цена не изменилась, но категория изменилась, тегируем
            group.loc[index, 'tag'] = 'FLAG'

        # Обновляем предыдущее значение
        prev_price = row['price']
        prev_category = row['category']

    return group

# Применяем функцию по группам "product" и "version"
df = df.groupby(['product', 'version'], as_index=False).apply(tag_rows)

Шаг 3: Проверка результата

Теперь вы можете проверить ваш DataFrame:

print(df)

Шаг 4: Объяснение работы кода

  1. Импортируем необходимых библиотеки: Используем pandas для работы с табличными данными.
  2. Создаем DataFrame: Инициализируем DataFrame из ваших данных.
  3. Добавляем столбец ‘tag’: Устанавливаем ему предначальное значение ‘OK’.
  4. Создаем функцию ‘tag_rows’: Проходим по каждой группе (по продукту и версии) и сравниваем текущую строку с предыдущей. Если цена не изменилась, но категория изменилась, ставим тег ‘FLAG’.
  5. Применяем функцию: Группируем DataFrame по продукту и версии, применяем функцию для тегирования.

Таким образом, вы получаете DataFrame с нужными тегами, отвечающими вашему запросу.

Оцените материал
Добавить комментарий

Капча загружается...