Заполнение дат в фрейме с тройным индексом - PullRequest
0 голосов
/ 24 января 2019

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

 Date        Product    eCommerce   Sales
12-10-2018      A           1        10
12-12-2018      A           0        7
12-13-2018      A           1        4
12-15-2018      A           1        2
12-15-2018      A           0        2
12-11-2018      B           1        8
12-13-2018      B           1        6

Поэтому мне нужно знать продажи с и без электронной коммерции для каждой даты и заполнять даты, которые не появляются, с нулевыми продажами . Мой желаемый результат будет:

 Date        Product    eCommerce   Sales
12-10-2018      A           1        10
12-11-2018      A           1        0
12-12-2018      A           1        0
12-13-2018      A           1        4
12-14-2018      A           1        0
12-15-2018      A           1        2

12-12-2018      A           0        7
12-13-2018      A           0        0
12-14-2018      A           0        0
12-15-2018      A           0        2

12-11-2018      B           1        8
12-12-2018      B           1        0
12-13-2018      B           1        6

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

Таким образом, в исходных фреймах данных 12-11 и 12-14 отсутствуют для электронной коммерции Продажи продукта А, 12-13 и 12-14 для не-электронной коммерции Продажи продукта А и 12-12 отсутствуют для электронной коммерции Продажи продукта B

Дело в том, что мне удалось добиться того, чего я хочу, с помощью очень неэффективного цикла, который занимает около 25 минут:

df_full= pd.DataFrame(columns=df.columns)
for sku in df['Product'].unique():

    aux=df.loc[df['Product']==sku]
    dates= pd.DataFrame(pd.date_range(start=aux.Date.min(), end=aux.Date.max(),freq='D'),columns=['Date'])

    df3 = df.loc[df['id_prod']==sku].merge(dates,
                                                   how='outer',left_on='Date',
                                                   right_on='Date').sort_values(by='Date')

    df3.fillna(method='ffill',inplace=True)
    df_full= df_full.append(df3)

Я вполне уверен, что могу сделать это векторизованным способом, который должен занять меньше времени (у меня 2300 продуктов на 290 возможных дат). Вы знаете, как мне этого добиться?

Редактировать: добавлен жирный текст с лучшим объяснением проблемы

1 Ответ

0 голосов
/ 24 января 2019

Используйте один DatetimeIndex, затем groupby + resample.asfreq() (можно использовать сумму для числовых столбцов), поскольку диапазон дат зависит от группы.

import pandas as pd

df['Date'] = pd.to_datetime(df.Date)
df = df.set_index('Date')

df.groupby(['Product', 'eCommerce'], sort=False).Sales.resample('D').sum().reset_index()

Если у вас много столбцов, которые вы хотите заполнить нулями, то:

(df.groupby(['Product', 'eCommerce'], sort=False)
    .resample('D').sum()
    .drop(columns=['Product', 'eCommerce'])
    .reset_index())

Выход:

   Product  eCommerce       Date  Sales
0        A          1 2018-12-10     10
1        A          1 2018-12-11      0
2        A          1 2018-12-12      0
3        A          1 2018-12-13      4
4        A          1 2018-12-14      0
5        A          1 2018-12-15      2
6        A          0 2018-12-12      7
7        A          0 2018-12-13      0
8        A          0 2018-12-14      0
9        A          0 2018-12-15      2
10       B          1 2018-12-11      8
11       B          1 2018-12-12      0
12       B          1 2018-12-13      6
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...