У меня есть фрейм данных pandas, который содержит данные временных рядов, поэтому индекс фрейма имеет тип datetime64 с недельными интервалами, каждая дата происходит в понедельник каждой календарной недели.
В кадре данных есть только записи, когда был записан заказ, поэтому, если не было заказа, в кадре данных нет соответствующей записи. Я хотел бы "заполнить" эту фреймворк так, чтобы любые недели в определенном диапазоне дат были включены в dataframe и вводится соответствующее нулевое количество.
Мне удалось получить эту работу, создав фиктивный фреймворк данных, который включает запись для каждой недели, которую я хочу с нулевым количеством, а затем слияние этих двух фреймов данных и удаление столбца фиктивного столбца данных. Это приводит к 3-му заполненному файловому кадру.
Я не чувствую, что это отличное решение проблемы, а новое для панд хотело узнать, есть ли более конкретный и или путинский способ достичь этого, возможно, без необходимости создания фиктивного фрейма данных и затем слияния.
Код, который я использовал ниже, чтобы получить мое текущее решение:
# Create the dummy product
# Week hold the week date of the order, want to set this as index later
group_by_product_name = df_all_products.groupby(['Week', 'Product Name'])['Qty'].sum()
first_date = group_by_product_name.head(1) # First date in entire dataset
last_date = group_by_product_name.tail().index[-1] # last date in the data set
bdates = pd.bdate_range(start=first_date, end=last_date, freq='W-MON')
qty = np.zeros(bdates.shape)
dummy_product = {'Week':bdates, 'DummyQty':qty}
df_dummy_product = pd.DataFrame(dummy_product)
df_dummy_product.set_index('Week', inplace=True)
group_by_product_name = df_all_products.groupby('Week')['Qty'].sum()
df_temp = pd.concat([df_dummy_product, group_by_product_name], axis=1, join='outer')
df_temp.fillna(0, inplace=True)
df_temp.drop(columns=['DummyQty'], axis=1, inplace=True)
Проблема с этим подходом иногда (я не знаю, почему) индексы не соответствуют правильно, я думаю, что как-то dtype индекса на одном из dataframes теряет свой тип и переходит к объекту вместо того, чтобы оставаться с dtype datetime64. Поэтому я уверен, что есть лучший способ решить эту проблему, чем мое текущее решение.
РЕДАКТИРОВАТЬ
Вот примерный кадр данных с "отсутствующими записями"
df1 = pd.DataFrame({'Week':['2018-05-28', '2018-06-04',
'2018-06-11', '2018-06-25'], 'Qty':[100, 200, 300, 500]})
df1.set_index('Week', inplace=True)
df1.head()
Ниже приведен пример заполненного фрейма данных, который содержит дополнительные отсутствующие даты между диапазоном дат
df_zero = pd.DataFrame({'Week':['2018-05-21', '2018-05-28', '2018-06-04',
'2018-06-11', '2018-06-18', '2018-06-25', '2018-07-02'], 'Dummy Qty':[0, 0, 0, 0, 0, 0, 0]})
df_zero.set_index('Week', inplace=True)
df_zero.head()
И это намеченный результат после конкатенации двух информационных кадров
df_padded = pd.concat([df_zero, df1], axis=1, join='outer')
df_padded.fillna(0, inplace=True)
df_padded.drop(columns=['Dummy Qty'], inplace=True)
df_padded.head(6)
Обратите внимание, что отсутствующие записи добавляются до и между другими записями, где это необходимо в окончательном кадре данных.
Изменить 2:
В соответствии с просьбой здесь приведен пример того, как будет выглядеть исходный файл данных:
df_all_products = pd.DataFrame({'Week':['2018-05-21', '2018-05-28', '2018-05-21', '2018-06-11', '2018-06-18',
'2018-06-25', '2018-07-02'],
'Product Name':['A', 'A', 'B', 'A', 'B', 'A', 'A'],
'Qty':[100, 200, 300, 400, 500, 600, 700]})
Хорошо, учитывая ваши исходные данные, вы можете достичь ожидаемых результатов, используя pivot
точку и повторную выборку для любых отсутствующих недель, например:
results = df_all_products.groupby(
['Week','Product Name']
)['Qty'].sum().reset_index().pivot(
index='Week',columns='Product Name', values='Qty'
).resample('W-MON').asfreq().fillna(0)
Результаты вывода:
Product Name A B
Week
2018-05-21 100.0 300.0
2018-05-28 200.0 0.0
2018-06-04 0.0 0.0
2018-06-11 400.0 0.0
2018-06-18 0.0 500.0
2018-06-25 600.0 0.0
2018-07-02 700.0 0.0
Поэтому, если вы хотите получить df
для Product Name A, вы можете сделать results['A']
.