Добавить недостающие даты для панды фрейма данных
мои данные могут иметь несколько событий на заданную дату или никаких событий на дату. Я беру эти события, подсчитываю по дате и строю их. Однако, когда я строю их, мои две серии не всегда совпадают.
idx = pd.date_range(df['simpleDate'].min(), df['simpleDate'].max())
s = df.groupby(['simpleDate']).size()
В приведенном выше коде idx становится диапазон скажем 30 дат. 09-01-2013 в 09-30-2013
Однако S может быть только 25 или 26 дней, потому что нет событий на указанную дату. Затем я получаю AssertionError, поскольку размеры не совпадают, когда я пытаюсь сюжет:
fig, ax = plt.subplots()
ax.bar(idx.to_pydatetime(), s, color='green')
каков правильный способ справиться с этим? Я хочу удалить даты без значений из IDX или (что я бы предпочел сделать) добавить в серию недостающую дату с количеством 0. Я бы предпочел полный график 30 дней с 0 значениями. Если этот подход верен, какие-либо предложения о том, как начать работу? Мне нужен какой-то динамический ?
вот фрагмент S (df.groupby(['simpleDate']).size()), обратите внимание на отсутствие записей для 04 и 05.
09-02-2013 2
09-03-2013 10
09-06-2013 5
09-07-2013 1
5 ответов:
вы могли бы использовать
Series.reindex:import pandas as pd idx = pd.date_range('09-01-2013', '09-30-2013') s = pd.Series({'09-02-2013': 2, '09-03-2013': 10, '09-06-2013': 5, '09-07-2013': 1}) s.index = pd.DatetimeIndex(s.index) s = s.reindex(idx, fill_value=0) print(s)доходность
2013-09-01 0 2013-09-02 2 2013-09-03 10 2013-09-04 0 2013-09-05 0 2013-09-06 5 2013-09-07 1 2013-09-08 0 ...
одна проблема заключается в том, что
reindexне удастся, если есть повторяющиеся значения. Скажем, мы работаем с данными с отметками времени, которые мы хотим индексировать по дате:df = pd.DataFrame({ 'timestamps': pd.to_datetime( ['2016-11-15 1:00','2016-11-16 2:00','2016-11-16 3:00','2016-11-18 4:00']), 'values':['a','b','c','d']}) df.index = pd.DatetimeIndex(df['timestamps']).floor('D') dfдоходность
timestamps values 2016-11-15 "2016-11-15 01:00:00" a 2016-11-16 "2016-11-16 02:00:00" b 2016-11-16 "2016-11-16 03:00:00" c 2016-11-18 "2016-11-18 04:00:00" dиз-за дубликата
2016-11-16дата, попытка переиндексации:all_days = pd.date_range(df.index.min(), df.index.max(), freq='D') df.reindex(all_days)выдает:
... ValueError: cannot reindex from a duplicate axis(это означает, что индекс имеет дубликаты, а не то, что он сам dup)
вместо этого мы можем использовать
.locпосмотреть записи для всех даты в диапазоне:df.loc[all_days]доходность
timestamps values 2016-11-15 "2016-11-15 01:00:00" a 2016-11-16 "2016-11-16 02:00:00" b 2016-11-16 "2016-11-16 03:00:00" c 2016-11-17 NaN NaN 2016-11-18 "2016-11-18 04:00:00" d
fillnaможет использоваться в серии столбцов для заполнения пробелов, если это необходимо.
более быстрый способ-это использовать
.asfreq(). Это не требует создания нового индекса для вызова в пределах.reindex().# "broken" (staggered) dates dates = pd.Index([pd.Timestamp('2012-05-01'), pd.Timestamp('2012-05-04'), pd.Timestamp('2012-05-06')]) s = pd.Series([1, 2, 3], dates) print(s.asfreq('D')) 2012-05-01 1.0 2012-05-02 NaN 2012-05-03 NaN 2012-05-04 2.0 2012-05-05 NaN 2012-05-06 3.0 Freq: D, dtype: float64
во многих случаях
resample(см. документацию здесь) предлагает общее решение, которое может обрабатывать как отсутствующие и повторяющиеся даты. Например:df.resample('D').mean()
resampleэто отложенная операция, какgroupbyпоэтому вам нужно следовать за ним с другой операцией. В данном случаеmeanработает хорошо, но вы также можете использовать многие стандартные панды метод там, какmax,sumи т. д.вот исходные данные, но с дополнительной записью для '2013-09-03':
val date 2013-09-02 2 2013-09-03 10 2013-09-03 20 2013-09-06 5 2013-09-07 1и вот результаты:
val date 2013-09-02 2.0 2013-09-03 15.0 <- mean of original values for 2013-09-03 2013-09-04 NaN <- NaN b/c date not present in orig 2013-09-05 NaN <- NaN b/c date not present in orig 2013-09-06 5.0 2013-09-07 1.0обратите внимание, что после этого вы можете использовать такие методы, как
fillnaилиinterpolateдля заполнения пропущенных значений по желанию.
вот хороший способ, чтобы заполнить недостающие даты в таблице данных, с выбором
fill_value,days_backдля заполнения и порядок сортировки (date_order), который используется для сортировки таблицы данных:def fill_in_missing_dates(df, date_col_name = 'date',date_order = 'asc', fill_value = 0, days_back = 30): df.set_index(date_col_name,drop=True,inplace=True) df.index = pd.DatetimeIndex(df.index) d = datetime.now().date() d2 = d - timedelta(days = days_back) idx = pd.date_range(d2, d, freq = "D") df = df.reindex(idx,fill_value=fill_value) df[date_col_name] = pd.DatetimeIndex(df.index) return df
Comments