У меня есть df в пандах с ежедневными данными. Я хотел бы вернуть последнее значение каждого месяца. Я подумал, что простое решение будет состоять в том, чтобы .resample("M").apply(lambda ser: ser.iloc[-1,])
однако, кажется, что resample
фактически вычисляет дату окончания месяца, а не возвращает фактическую дату который появляется в этом месяце. Это намеренное поведение? MWE:
import pandas as pd
import numpy as np
df = pd.Series(np.arange(100), index=pd.date_range(start="2000-01-02", periods=100)).to_frame()
df.sort_index().resample("M").apply(lambda ser: ser.iloc[-1,])
# 0
#2000-01-31 29
#2000-02-29 58
#2000-03-31 89
#2000-04-30 99
Хотя последняя дата, отображаемая в df
равна 2000-04-10
Используя resample
со смещением M
, вы уменьшаете выборку до конца календаря (см. Связанную документацию по смещениям), а затем передаете функцию. Таким образом, ваши индексы всегда будут последним днем этого месяца, и это действительно намеченное поведение. Функция, которую вы применяете (lambda ser: ser.iloc[-1,]
), просто говорит: для календарной даты, которая заканчивается в этот день, каково последнее значение, найденное в исходных данных.
Например, вы также можете перепрограммировать до начала месяца, используя смещенную MS
вместо M
, и результат будет таким же, за исключением того, что индекс будет первым днем календарного месяца, а не последним днем:
# Resample to month end, as you had originally:
>>> df.sort_index().resample("M").apply(lambda ser: ser.iloc[-1,])
0
2000-01-31 29
2000-02-29 58
2000-03-31 89
2000-04-30 99
# Resample to month start: same data, except index is month start instead of month end
>>> df.sort_index().resample("MS").apply(lambda ser: ser.iloc[-1,])
0
2000-01-01 29
2000-02-01 58
2000-03-01 89
2000-04-01 99
Как указал Вэнь Цзябао, если вы просто хотите показать фактическую последнюю дату, найденную в ваших данных, вам будет лучше с группой. Resample полезен, если вы хотите, чтобы up- или down- использовали ваши данные на другой временной частоте, а не столько для выбора реальных данных с вашей исходной временной частоты
Вам может потребоваться посмотреть на groupby
+ tail
df.groupby(df.index.month).tail(1)
Out[18]:
0
2000-01-31 29
2000-02-29 58
2000-03-31 89
2000-04-10 99
tail
: спрашивать, почемуresample
составляет последнюю дату месяца, а не возвращает фактическую дату, которая появляется в этом месяце. ваше решение работает (хотя и потерпит неудачу в течение нескольких лет)