2025, Dec 12 03:02
Нормализуем Delivery Period в pandas: диапазон в месяцы Month Year
Пошагово нормализуем столбец Delivery Period в pandas: распознаем диапазон дат, генерируем месяцы period_range, применяем explode и форматируем в вид Month Year
Приведите к единому виду смешанный столбец “Delivery Period”: разверните один строковый диапазон вроде “2025-01-01 to 2025-12-31” в отдельные строки по одному месяцу и сохраните уже заданные значения формата месяц–год без изменений. Ниже — компактный подход на pandas: он обнаруживает диапазон, генерирует месячные периоды, «взрывает» их в строки и форматирует результат в ожидаемый вид “Month Year”.
Задача
Часть строк хранит период поставки как строку с датами начала и конца вместо требуемого формата “Month Year”. Нужно найти такие строки и преобразовать каждую в несколько строк — по одной на каждый месяц диапазона — при этом остальные столбцы должны оставаться без изменений.
Воспроизводимый пример
Входные данные содержат один годовой диапазон и несколько значений уже в нормализованном виде «месяц‑год».
import pandas as pd
seed_cols = {
'Price Curve': [
'TEST',
'some curve',
'some curve',
'some curve',
'some curve',
'some curve',
'some curve',
'some curve'
],
'Text': [
'TEST',
'some text',
'some text',
'some text',
'some text',
'some text',
'some text',
'some text'
],
'Delivery Period': [
'2025-01-01 to 2025-12-31',
'June 2025',
'July 2025',
'August 2025',
'September 2025',
'October 2025',
'November 2025',
'December 2025'
]
}
frame = pd.DataFrame(seed_cols)
Что происходит и зачем
В столбце смешаны два представления времени: единая строка «от начала до конца», охватывающая несколько месяцев, и отдельные строки в формате “Month Year”. Чтобы выровнять модель данных, диапазон нужно превратить в месячную последовательность и развернуть в отдельные строки. Самый простой надежный признак — подстрока, разделяющая границы диапазона.
Решение
Стратегия такова: определить строки с диапазоном, разделить границы, построить месячную последовательность, развернуть последовательность в строки, отформатировать результат как “Month Year”, а затем вернуть значения в исходный столбец.
# Определяем строки, содержащие диапазон дат
has_span = frame['Delivery Period'].str.contains(' to ')
# Разбиваем текстовый диапазон на начало/конец и генерируем месячные периоды
frame.loc[has_span, 'span_seq'] = frame.loc[has_span, 'Delivery Period'].str.split(' to ')
frame.loc[has_span, 'span_seq'] = frame.loc[has_span, 'span_seq'].transform(
lambda pair: pd.period_range(pair[0], pair[1], freq='M')
)
# Разворачиваем по строке на период и форматируем как "Month Year"
frame = frame.explode('span_seq')
frame['span_seq'] = frame['span_seq'].dt.strftime('%B %Y')
# Если есть развернутое значение — берем его, иначе оставляем исходное
frame['Delivery Period'] = frame['span_seq'].combine_first(frame['Delivery Period'])
# Удаляем временный вспомогательный столбец
frame = frame.drop(columns='span_seq')
Почему это важно
Единая логика времени в поле “Delivery Period” упрощает дальнейшую обработку. Когда каждому месяцу соответствует своя строка, последующие шаги работают с ожидаемым форматом и совпадают с образцом результата, избегая неоднозначности, возникающей из-за одного широкого строкового диапазона.
Итоги
Легко выявляйте диапазон, преобразуйте его в месячную последовательность и разворачивайте строки. Связка генерации периодов, explode и финального форматирования дает чистый, единообразный столбец “Month Year”, не затрагивая строки, которые уже были оформлены корректно.