Как получить скользящее среднее за последние месяцы в пандах

У меня есть набор данных, в котором первый столбец - это дата, а второй - цена. Дата - торговые дни.

введите описание изображения здесь

Я хочу вернуть таблицу, которая выглядит так:

введите описание изображения здесь

Если дата - каждый месяц, начиная с 2006 г., MA - средняя цена за последние N месяцев (N = [1,2,3,4,5,6]).

Так, например: Если я хочу, чтобы N = 1 на 1 января 2006 года, млн. Лет должна быть средней ценой с декабря прошлого года. Если N = 2 млн. Лет, должна быть средняя цена с ноября по декабрь прошлого года.

Я прочитал какое-то решение об извлечении месяца из datetime и groupby. Но не знаю, как их сложить.


person Dylan    schedule 22.08.2017    source источник
comment
Посмотрите здесь и используйте прокрутку значит   -  person 2Obe    schedule 22.08.2017


Ответы (3)


Или вы просто попробуете

df.sort_index(ascending=False).rolling(5).mean().sort_index(ascending=True)

Для вашего дополнительного вопроса

index=pd.date_range(start="4th of July 2017",periods=30,freq="D")
df=pd.DataFrame(np.random.randint(0,100,30),index=index)
df['Month']=df.index
df.Month=df.Month.astype(str).str[0:7]
df.groupby('Month')[0].mean()


Out[162]: 
Month
2017-07    47.178571
2017-08    56.000000
Name: 0, dtype: float64

РЕДАКТИРОВАТЬ 3: для пропущенного значения, скользящего средним за два месяца

index=pd.date_range(start="4th of July 2017",periods=300,freq="D")
df=pd.DataFrame(np.random.randint(0,100,300),index=index)
df['Month']=df.index
df.Month=df.Month.astype(str).str[0:7]
df=df.groupby('Month')[0].agg({'sum':'sum','count':'count'})
df['sum'].rolling(2).sum()/df['count'].rolling(2).sum()


Out[200]: 
Month
2017-07          NaN
2017-08    43.932203
2017-09    45.295082
2017-10    46.967213
2017-11    46.327869
2017-12    49.081967
#etc
person BENY    schedule 22.08.2017
comment
В сочетании с dropna, чтобы избавиться от значений NA в конце, например df.sort_index().rolling(5).mean().dropna() - person 2Obe; 23.08.2017
comment
@ 2 Может быть, он хочет fillna с какой-нибудь ценностью - person BENY; 23.08.2017
comment
с помощью прокрутки (5) мы фиксируем числа наблюдений до 5, верно? Но количество торговых дней в предыдущем месяце не является фиксированным. - person Dylan; 23.08.2017
comment
@Dylan, тогда вам понадобится resample pandas.pydata.org/ pandas-docs / стабильный / сгенерированный / - person BENY; 23.08.2017
comment
@Wen Спасибо, я обнаружил, что df.resample ('M'). Mean () точно решает мою проблему, когда N = 1. Когда я хочу попробовать случай, когда N = 2. Я использовал df.resample ('2M'). Mean () Я получаю январь, март, май, июль. Цифры - те, которые мне нужны (среднее значение за последние 2 месяца). Однако у меня нет цен на февраль, апрель и так далее. Как мне это изменить? - person Dylan; 23.08.2017
comment
@Dylan, и вы можете посмотреть на fillna, есть метод, называемый ffill и bfill - person BENY; 23.08.2017
comment
@Wen Это не сработает, поскольку отсутствуют пропущенные значения. Я считаю, что этот вопрос такой же, как и мой: stackoverflow.com/questions/24875671/ Он пояснил, почему повторная выборка не работает для N› 1 случай - person Dylan; 23.08.2017
comment
@Wen Спасибо за обновление, но я думаю, что обновленный ответ дает только среднее значение за последний месяц, верно? Если это так, эффект будет таким же, как при использовании resample ('M'). Что, если мне нужно среднее значение за последние 3,4,5 месяца? - person Dylan; 23.08.2017
comment
@Dylan, как вы сказали, у вас отсутствуют данные. Итак, для M = 2 января + марта или января + февраля? - person BENY; 23.08.2017

Вернет скользящее среднее для количества периодов, указанных в параметре окна. Например. window = 1 вернет исходный список. Window = 2 вычислит среднее значение за 2 дня и так далее.

index=pd.date_range(start="4th of July 2017",periods=30,freq="D")



df=pd.DataFrame(np.random.randint(0,100,30),index=index)


print([pd.rolling_mean(df,window=i,freq="D") for i in range(1,5)])

.....

2017-07-04   NaN
2017-07-05  20.5
2017-07-06  64.5
2017-07-07  58.5
2017-07-08  13.0
2017-07-09   4.5
2017-07-10  17.5
2017-07-11  23.5
2017-07-12  40.5
2017-07-13  60.0
2017-07-14  73.0
2017-07-15  90.0
2017-07-16  56.5
2017-07-17  55.0
2017-07-18  57.0
2017-07-19  45.0
2017-07-20  77.0
2017-07-21  46.5
2017-07-22   3.5
2017-07-23  48.5
2017-07-24  71.5
2017-07-25  52.0
2017-07-26  56.5
2017-07-27  47.5
2017-07-28  64.0
2017-07-29  82.0
2017-07-30  68.0
2017-07-31  72.5
2017-08-01  58.5
2017-08-02  67.0

.....

Кроме того, вы можете удалить значения NA с помощью метода df dropna, например:

df.rolling(window=2,freq="D").mean().dropna() #Here you must adjust the window  size

Итак, весь код, который должен напечатать скользящее среднее за месяцы, выглядит так:

print([df.rolling(i,freq="m").mean().dropna() for i in range(len(df.rolling(window=1,freq="m").sum()))])
person 2Obe    schedule 22.08.2017
comment
Однако количество торговых дней в конкретном месяце не является фиксированным. Что мне с этим делать - person Dylan; 23.08.2017
comment
Вы можете установить периодичность в месяц - person 2Obe; 23.08.2017
comment
df.sort_index().rolling(1,freq="m").mean().dropna() со ссылкой на Вэнь - person 2Obe; 23.08.2017
comment
Это займет месяц как периодичность, независимо от того, сколько дней в месяце. - person 2Obe; 23.08.2017
comment
Но, естественно, вы должны настроить параметр частоты - person 2Obe; 23.08.2017

Сначала установите Date как индекс:

price_df.set_index('Date', inplace=True)
price_df.index = pd.to_datetime(price_df.index)

Затем рассчитайте скользящее среднее за последние N месяцев:
mv = price_df.rolling(window=i*30, center=False).mean().dropna() для N=i

Наконец, возвращайте подмножество только с первым днем ​​каждого месяца (если это то, что вы хотите вернуть):
mv.ix[mv.index.day==1]

person Yanfei W.    schedule 22.08.2017
comment
Вы предполагаете, что в каждом месяце 30 дней, что неверно. - person 2Obe; 23.08.2017