#pandas #mean
#панды #имею в виду
Вопрос:
Это мой первый пост здесь, и я надеюсь, что делаю это правильно. Я искал свой вопрос на форуме, и хотя там есть смежные темы, ни одна из них не касалась моего конкретного вопроса, поэтому я надеюсь, что вы сможете мне помочь.
У меня есть фрейм данных с двумя столбцами, который в упрощенном виде выглядит следующим образом:
Date Value
0 20010425 1
1 20010112 4
2 20010308 3
3 20010527 5
4 20010620 2
Первый столбец представляет даты в формате ггггммдд, но имеет значение int64.
Теперь я хочу создать дополнительный столбец, который принимает среднее значение за предыдущие 3 месяца индивидуально для каждой строки:
Date Value Mean_Value_past_3_months
0 20010425 1 3.5 #(4 3)/2
1 20010130 4 NaN # since no date earlier than 20010130 is available
2 20010308 3 4
3 20010527 5 2 # (1 3)/2
4 20010620 2 3 # (1 5)/2
И тогда я хотел бы отказаться от NaN, так что это не считается их продвижением вперед.
Я попытался перенести даты, а затем сделать это, и это то, что я нашел здесь:
s = subset.columns[0:].values < df.values[:,None]
df['mean'] = (subset.iloc[:,0:]*t).mean(1)
но это а) еще не работает, и б) не включает в себя 3-месячный период.
Спасибо за вашу помощь!!
Ответ №1:
Немного неоднозначно, как вы хотите определить «предыдущие три месяца», но вы можете сделать следующее:
import pandas as pd
df = pd.DataFrame({"Date": [20010425, 20010112, 20010308, 20010527, 20010620],
"Value": [1, 4, 3, 5, 2]
})
# define a custom function that computes the mean of the last three months
def get_mean(row):
# choose the correct dates here using the passed row parameter:
# e.g.
yyyymmdd_start = row["Date"] - 300
yyyymmdd_end = row["Date"]
selected_dates = df[(df['Date'] > yyyymmdd_start) amp; (df['Date'] < yyyymmdd_end)]
return selected_dates["Value"].mean()
df["Mean_Value_past_3_months"] = df.apply(get_mean, axis=1)
print(df)
Out[115]:
Date Value Mean_Value_past_3_months
0 20010425 1 3.0
1 20010112 4 NaN
2 20010308 3 4.0
3 20010527 5 2.0
4 20010620 2 3.0
Комментарии:
1. Привет, Андре, большое тебе спасибо за твою помощь!! Когда вы говорите «выберите правильные даты здесь», что вы имеете в виду под этим? Потому что начальная дата отличается для каждой строки, а затем я просматриваю последние 3 месяца для каждой строки в отдельности. Не могли бы вы уточнить? (К вашему сведению: код работает, но он дает мне значение для самой ранней даты, чего не должно быть)
2. В
get_mean()
функцииrow
параметр содержит информацию для этой строки. Таковоrow["Date"]
и значение даты для переданной строки (для строки с индексом 3 это будет20010527
. Я вычитаю 300 для этого значения, чтобы получить дату (в формате ггггммдд) 3 месяца назад. Это не оптимально, но это был просто простой способ получить 3 месяца от даты в заданной строке. Вот почему я говорю выбрать правильный путь.selected_dates
затем является фреймом данных, который содержит только строки в пределах выбранного интервала времени (3 месяца), наконец, функция возвращает среднее значение значений. Надеюсь, это поможет3. Как это делает Фил Лех ниже, вы можете упростить себе жизнь, преобразовав формат даты в формат, с которым pandas работает изначально. Это открывает гораздо больше возможностей.
4. Абсолютно логично, спасибо!
Ответ №2:
Другим подходом может быть преобразование целых дат в datetime и использование pandas.Возможности DataFrame.rolling, подобные этому:
import pandas as pd
df['Date'] = pd.to_datetime(dates, format='%Y%m%d')
# Sorting by Date, because rolling() need monotonic dates
df = df.sort_values('Date')
# Using approximately 30 days per month -> 90 day for 3 months, hence '90D'
df['Means'] = df.rolling('90D', on='Date', closed='left').mean()['Value']
print(df)
Это приведет к:
Date Value Means
1 2001-01-30 4 NaN
2 2001-03-08 3 4.0
0 2001-04-25 1 3.5
3 2001-05-27 5 2.0
4 2001-06-20 2 3.0
Комментарии:
1. Большое тебе спасибо, Фил! V полезно!