расширить датафрейм с несуществующими датами - PullRequest
0 голосов
/ 18 октября 2019

У меня есть датафрейм, содержащий нерегулярные события времени. Я хотел бы расширить его, добавив дополнительные строки (сначала пустые, которые будут заполнены позже) для каждой недели, которой еще нет. Это то, что у меня есть:

import pandas as pd

df = pd.DataFrame({'id' : [1,1,2,2,2],
               'date': ['2019-01-01', '2019-02-01', '2019-01-01', '2019-03-01', '2019-05-01'],
               'value': [100, 200, 300, 400, 500]})
df["week"] = pd.to_datetime(df["date"]).dt.to_period('W')


all_weeks = pd.period_range(min(df["date"]), max(df["date"]), freq='W')

all_weeks
PeriodIndex(['2018-12-31/2019-01-06', '2019-01-07/2019-01-13',
         '2019-01-14/2019-01-20', '2019-01-21/2019-01-27',
         '2019-01-28/2019-02-03', '2019-02-04/2019-02-10',
         '2019-02-11/2019-02-17', '2019-02-18/2019-02-24',
         '2019-02-25/2019-03-03', '2019-03-04/2019-03-10',
         '2019-03-11/2019-03-17', '2019-03-18/2019-03-24',
         '2019-03-25/2019-03-31', '2019-04-01/2019-04-07',
         '2019-04-08/2019-04-14', '2019-04-15/2019-04-21',
         '2019-04-22/2019-04-28', '2019-04-29/2019-05-05'],
        dtype='period[W-SUN]', freq='W-SUN')

Мои данные покрывают 18 недель, поэтому я бы хотел, чтобы df было расширено таким образом, чтобы оно имело 18 * 2 = 36 строк, с пустыми valuesдля вновь добавленных строк, но оба раза id появляются 18 раз. Как мне этого добиться?

Ожидаемый результат :

id    week                     value
1.0   '2018-12-31/2019-01-06'  100
1.0   '2019-01-07/2019-01-13'  NaN
...
1.0   '2019-04-29/2019-05-05'  NaN
2.0   '2018-12-31/2019-01-06'  300
2.0   '2019-01-07/2019-01-13'  NaN
...

Я предполагаю, что это внешнее слияние по столбцу week, но я не понялего еще.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Изменить 2019-10-20

Пользовательская функция, применяемая для id группы:

 def period_index(df, num_weeks=36):
   weeks = pd.period_range(min(df["date"]), 
                               periods=num_weeks, 
                               freq='W', 
                               name='week')
   return df.reindex(weeks).drop('id', axis=1)

Установить индекс в df:

df.set_index('week', inplace=True)

Сгруппируйте id и примените нашу функцию, очистите столбцы и индекс:

df.groupby('id').apply(period_index).reset_index().drop('date', axis=1)

Пример вывода:

    id                   week  value
0    1  2018-12-31/2019-01-06  100.0
1    1  2019-01-07/2019-01-13    NaN
2    1  2019-01-14/2019-01-20    NaN
3    1  2019-01-21/2019-01-27    NaN
4    1  2019-01-28/2019-02-03  200.0
5    1  2019-02-04/2019-02-10    NaN
6    1  2019-02-11/2019-02-17    NaN
7    1  2019-02-18/2019-02-24    NaN
8    1  2019-02-25/2019-03-03    NaN
9    1  2019-03-04/2019-03-10    NaN
....
62   2  2019-07-01/2019-07-07    NaN
63   2  2019-07-08/2019-07-14    NaN
64   2  2019-07-15/2019-07-21    NaN
65   2  2019-07-22/2019-07-28    NaN
66   2  2019-07-29/2019-08-04    NaN
67   2  2019-08-05/2019-08-11    NaN
68   2  2019-08-12/2019-08-18    NaN
69   2  2019-08-19/2019-08-25    NaN
70   2  2019-08-26/2019-09-01    NaN
71   2  2019-09-02/2019-09-08    NaN
0 голосов
/ 22 октября 2019

Я нашел альтернативное решение:

from itertools import product
all_weeks = pd.period_range(df["date"].min(), df["date"].max(), freq='W')
all_snrs = df["id"].unique()
all_rows = pd.DataFrame(product(all_weeks, all_snrs), columns=["week", "id"])
output = pd.merge(all_rows, df, how='outer').sort_values(by=["id", "week"])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...