Добавить недостающие даты для панды фрейма данных



мои данные могут иметь несколько событий на заданную дату или никаких событий на дату. Я беру эти события, подсчитываю по дате и строю их. Однако, когда я строю их, мои две серии не всегда совпадают.



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
724   5  

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

    Ничего не найдено.