Заполнение Python и пример

У меня есть фрейм данных ниже, и, как вы заметили, EconomicDate — это начало квартала, и иногда значения в EconomicDate отсутствуют. Я хотел бы иметь непрерывные ежемесячные даты в столбце «Эффективная дата», при этом все столбцы будут заполнены из самой последней эффективной даты.

Пример: для каждой группы = A, поскольку значения для эффективной даты = 01.02.2022 и 1.03.2022 отсутствуют, поэтому необходимо заполнить все значения столбцов с 1 января 2022 года и т. д.

Входной ДФ:

import pandas as pd
    
data = {
        'Group': ['A'] * 24,
        'EffectiveDate': [
            '1/1/2022', '1/1/2022', '1/1/2022', '1/1/2022', '1/1/2022', '1/1/2022',
            '4/1/2022', '4/1/2022', '4/1/2022', '4/1/2022', '4/1/2022', '4/1/2022',
            '7/1/2022', '7/1/2022', '7/1/2022', '7/1/2022', '7/1/2022', '7/1/2022',
            '10/1/2022', '10/1/2022', '10/1/2022', '10/1/2022', '10/1/2022', '10/1/2022'
        ],
        'ForecastDate': [
            '1/1/2022', '2/1/2022', '3/1/2022', '4/1/2022', '5/1/2022', '6/1/2022',
            '4/1/2022', '5/1/2022', '6/1/2022', '7/1/2022', '8/1/2022', '9/1/2022',
            '7/1/2022', '8/1/2022', '9/1/2022', '10/1/2022', '11/1/2022', '12/1/2022',
            '10/1/2022', '11/1/2022', '12/1/2022', '1/1/2023', '2/1/2023', '3/1/2023'
        ],
        'SKU': ['ABC12'] * 24,
        'Source': ['fdhh'] * 24
    }
    
df = pd.DataFrame(data)

Выходной ДФ:


    | Group |EffectiveDate| ForecastDate|   SKU| Source |
    |-------|------------|------------|--------|--------|
    | A     | 1/1/2022   | 1/1/2022   | ABC12  | fdhh   |
    | A     | 1/1/2022   | 2/1/2022   | ABC12  | fdhh   |
    | A     | 1/1/2022   | 3/1/2022   | ABC12  | fdhh   |
    | A     | 1/1/2022   | 4/1/2022   | ABC12  | fdhh   |
    | A     | 1/1/2022   | 5/1/2022   | ABC12  | fdhh   |
    | A     | 1/1/2022   | 6/1/2022   | ABC12  | fdhh   |
    | A     | 2/1/2022   | 2/1/2022   | ABC12  | fdhh   |
    | A     | 2/1/2022   | 3/1/2022   | ABC12  | fdhh   |
    | A     | 2/1/2022   | 4/1/2022   | ABC12  | fdhh   |
    | A     | 2/1/2022   | 5/1/2022   | ABC12  | fdhh   |
    | A     | 2/1/2022   | 6/1/2022   | ABC12  | fdhh   |
    | A     | 3/1/2022   | 3/1/2022   | ABC12  | fdhh   |
    | A     | 3/1/2022   | 4/1/2022   | ABC12  | fdhh   |
    | A     | 3/1/2022   | 5/1/2022   | ABC12  | fdhh   |
    | A     | 3/1/2022   | 6/1/2022   | ABC12  | fdhh   |
    | A     | 4/1/2022   | 4/1/2022   | ABC12  | fdhh   |
    | A     | 4/1/2022   | 5/1/2022   | ABC12  | fdhh   |
    | A     | 4/1/2022   | 6/1/2022   | ABC12  | fdhh   |
    | A     | 4/1/2022   | 7/1/2022   | ABC12  | fdhh   |
    | A     | 4/1/2022   | 8/1/2022   | ABC12  | fdhh   |
    | A     | 4/1/2022   | 9/1/2022   | ABC12  | fdhh   |
    | A     | 5/1/2022   | 5/1/2022   | ABC12  | fdhh   |
    | A     | 5/1/2022   | 6/1/2022   | ABC12  | fdhh   |
    | A     | 5/1/2022   | 7/1/2022   | ABC12  | fdhh   |
    | A     | 5/1/2022   | 8/1/2022   | ABC12  | fdhh   |
    | A     | 5/1/2022   | 9/1/2022   | ABC12  | fdhh   |
    | A     | 6/1/2022   | 6/1/2022   | ABC12  | fdhh   |
    | A     | 6/1/2022   | 7/1/2022   | ABC12  | fdhh   |
    | A     | 6/1/2022   | 8/1/2022   | ABC12  | fdhh   |
    | A     | 6/1/2022   | 9/1/2022   | ABC12  | fdhh   |
    | A     | 7/1/2022   | 7/1/2022   | ABC12  | fdhh   |
    | A     | 7/1/2022   | 8/1/2022   | ABC12  | fdhh   |
    | A     | 7/1/2022   | 9/1/2022   | ABC12  | fdhh   |
    | A     | 7/1/2022   | 10/1/2022  | ABC12  | fdhh   |
    | A     | 7/1/2022   | 11/1/2022  | ABC12  | fdhh   |
    | A     | 7/1/2022   | 12/1/2022  | ABC12  | fdhh   |
    | A     | 8/1/2022   | 8/1/2022   | ABC12  | fdhh   |
    | A     | 8/1/2022   | 9/1/2022   | ABC12  | fdhh   |
    | A     | 8/1/2022   | 10/1/2022  | ABC12  | fdhh   |
    | A     | 8/1/2022   | 11/1/2022  | ABC12  | fdhh   |
    | A     | 8/1/2022   | 12/1/2022  | ABC12  | fdhh   |
    | A     | 9/1/2022   | 9/1/2022   | ABC12  | fdhh   |
    | A     | 9/1/2022   | 10/1/2022  | ABC12  | fdhh   |
    | A     | 9/1/2022   | 11/1/2022  | ABC12  | fdhh   |
    | A     | 9/1/2022   | 12/1/2022  | ABC12  | fdhh   |
    | A     | 10/1/2022  | 10/1/2022  | ABC12  | fdhh   |
    | A     | 10/1/2022  | 11/1/2022  | ABC12  | fdhh   |
    | A     | 10/1/2022  | 12/1/2022  | ABC12  | fdhh   |
    | A     | 10/1/2022  | 1/1/2023   | ABC12  | fdhh   |
    | A     | 10/1/2022  | 2/1/2023   | ABC12  | fdhh   |
    | A     | 10/1/2022  | 3/1/2023   | ABC12  | fdhh   |
    | A     | 11/1/2022  | 11/1/2022  | ABC12  | fdhh   |
    | A     | 11/1/2022  | 12/1/2022  | ABC12  | fdhh   |
    | A     | 11/1/2022  | 1/1/2023   | ABC12  | fdhh   |
    | A     | 11/1/2022  | 2/1/2023   | ABC12  | fdhh   |
    | A     | 11/1/2022  | 3/1/2023   | ABC12  | fdhh   |
    | A     | 12/1/2022  | 12/1/2022  | ABC12  | fdhh   |
    | A     | 12/1/2022  | 1/1/2023   | ABC12  | fdhh   |
    | A     | 12/1/2022  | 2/1/2023   | ABC12  | fdhh   |
    | A     | 12/1/2022  | 3/1/2023   | ABC12  | fdhh   |

пожалуйста, добавьте еще одну группу к вашим данным, чтобы охватить несколько групп. также, пожалуйста, уменьшите количество строк во входном фрейме данных - с этим просто работать

sammywemmy 06.10.2023 07:31
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы можете преобразовать EffectiveDate в месячные периоды с помощью Serie.dt.to_ period , переделать с помощью GroupBy.cumcount и DataFrame.pivot , поэтому можно использовать DataFrame.reindex для каждой группы. Затем измените форму обратно с помощью DataFrame.stack, преобразуйте MultiIndex в столбцы и отфильтруйте ForecastDate, если они больше или равны, на EffectiveDate:

df['EffectiveDate'] = pd.to_datetime(df['EffectiveDate']).dt.to_period('m')
df['ForecastDate'] = pd.to_datetime(df['ForecastDate'])

out = (df.assign(g = df.groupby(['Group','EffectiveDate']).cumcount())
        .pivot(index=['Group','EffectiveDate'], columns='g')
        .reset_index(level=0)
        .groupby('Group')
        .apply(lambda x: x.reindex(pd.period_range(x.index.min(),
                                                   pd.Period(f'{x.index.max().year}-12')), 
                                   method='ffill'))
        .drop('Group', axis=1)
        .stack()
        .droplevel(2)
        .rename_axis(['Group','EffectiveDate'])
        .reset_index()
        .assign(EffectiveDate = lambda x: x['EffectiveDate'].dt.to_timestamp())
        .query('ForecastDate >= EffectiveDate'))

print (out.tail(15))
   Group EffectiveDate ForecastDate    SKU Source
54     A    2022-10-01   2022-10-01  ABC12   fdhh
55     A    2022-10-01   2022-11-01  ABC12   fdhh
56     A    2022-10-01   2022-12-01  ABC12   fdhh
57     A    2022-10-01   2023-01-01  ABC12   fdhh
58     A    2022-10-01   2023-02-01  ABC12   fdhh
59     A    2022-10-01   2023-03-01  ABC12   fdhh
61     A    2022-11-01   2022-11-01  ABC12   fdhh
62     A    2022-11-01   2022-12-01  ABC12   fdhh
63     A    2022-11-01   2023-01-01  ABC12   fdhh
64     A    2022-11-01   2023-02-01  ABC12   fdhh
65     A    2022-11-01   2023-03-01  ABC12   fdhh
68     A    2022-12-01   2022-12-01  ABC12   fdhh
69     A    2022-12-01   2023-01-01  ABC12   fdhh
70     A    2022-12-01   2023-02-01  ABC12   fdhh
71     A    2022-12-01   2023-03-01  ABC12   fdhh

Обновлено: Для динамической фильтрации по столбцу Group используйте вспомогательный словарь mapping с Series.map на последнем этапе фильтрации:

df['EffectiveDate'] = pd.to_datetime(df['EffectiveDate']).dt.to_period('m')
df['ForecastDate'] = pd.to_datetime(df['ForecastDate'])

mapping = {'A': '2022-10-01',
           'B':'2022-06-01'}

out = (df.assign(g = df.groupby(['Group','EffectiveDate']).cumcount())
        .pivot(index=['Group','EffectiveDate'], columns='g')
        .reset_index(level=0)
        .groupby('Group')
        .apply(lambda x: x.reindex(pd.period_range(x.index.min(),
                                                   pd.Period(f'{x.index.max().year}-12')), 
                                   method='ffill'))
        .drop('Group', axis=1)
        .stack()
        .droplevel(2)
        .rename_axis(['Group','EffectiveDate'])
        .reset_index()
        .assign(EffectiveDate = lambda x: x['EffectiveDate'].dt.to_timestamp())
        .loc[lambda x: (x['ForecastDate']  >= x['EffectiveDate']) &  
                       (x['EffectiveDate'] < x['Group'].map(mapping))]
            )

print(out.tail(10))
   Group EffectiveDate ForecastDate    SKU Source
41     A    2022-07-01   2022-12-01  ABC12   fdhh
43     A    2022-08-01   2022-08-01  ABC12   fdhh
44     A    2022-08-01   2022-09-01  ABC12   fdhh
45     A    2022-08-01   2022-10-01  ABC12   fdhh
46     A    2022-08-01   2022-11-01  ABC12   fdhh
47     A    2022-08-01   2022-12-01  ABC12   fdhh
50     A    2022-09-01   2022-09-01  ABC12   fdhh
51     A    2022-09-01   2022-10-01  ABC12   fdhh
52     A    2022-09-01   2022-11-01  ABC12   fdhh
53     A    2022-09-01   2022-12-01  ABC12   fdhh

Все работает хорошо! Но необходимо прекратить добавлять непрерывную дату вступления в силу после максимальной даты вступления в силу, т. е. 2022-10 гг. Пожалуйста, измените код. Спасибо

spartacus8w2039 06.10.2023 20:49

@spartacus8w2039, так что нужно поменять .query('ForecastDate >= EffectiveDate') на .query('(ForecastDate >= EffectiveDate) & (EffectiveDate < "2022-10-01")')

jezrael 06.10.2023 21:44

< «2022-10-01» не является статическим значением, оно должно быть динамическим для группы по группе A, максимальное значение — «2022-10-01», может быть другая группа «B», которая имеет «2022-06-01» ".

spartacus8w2039 12.10.2023 03:51

@ spartacus8w2039 - ответ отредактирован.

jezrael 12.10.2023 08:10

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