Статистика набора данных с пользовательским началом года

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

Я пробовал, например. следующее:

rollday = -181
dr = pd.date_range('2015-01-01', '2017-08-23')
foo = xr.Dataset({'data': (['time'], np.ones(len(dr)))}, coords={'time': dr})
foo_groups = foo.roll(time=rollday).groupby(foo.time.dt.year)
foo_cumsum = foo_groups.apply(lambda x: x.cumsum(dim='time', skipna=True))

что является «неблагоприятным» в основном из-за двух вещей: (1) скользящий период не учитывает високосные годы, поэтому получается смещение в один день на каждый високосный год и (2) начало первого года (до конца июнь) добавляется в конец свернутого временного ряда, что создает некий «фальшивый год», когда совокупные суммы больше не имеют смысла.

Пробовал также сначала обрезать концы временного ряда, но потом прокатка уже не работает. Ресэмплинг мне тоже не показался вариантом, так как я не смог найти подходящую строку частоты pandas.

Я уверен, что есть лучший/правильный способ сделать это. Кто-нибудь может помочь?


person user3017048    schedule 23.08.2017    source источник


Ответы (1)


Вы можете использовать xarray.DataArray для указания групп. Один из способов сделать это — создать массив значений (годов), которые определяют идентификаторы групп:

# setup sample data
dr = pd.date_range('2015-01-01', '2017-08-23')
foo = xr.Dataset({'data': (['time'], np.ones(len(dr)))}, coords={'time': dr})

# create an array of years (modify day/month for your use case)
my_years = xr.DataArray([t.year if ((t.month < 9) or ((t.month==9) and (t.day < 15))) else (t.year + 1) for t in foo.indexes['time']],
                        dims='time', name='my_years', coords={'time': dr})

# use that array of years (integers) to do the groupby
foo_cumsum = foo.groupby(my_years).apply(lambda x: x.cumsum(dim='time', skipna=True))

# Voila!
foo_cumsum['data'].plot()

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

person jhamman    schedule 24.08.2017
comment
Хорошо, я нашел ошибку в коде: чтобы выбрать my_years, условие должно быть что-то вроде ((t.month < 9) or ((t.month==9) and (t.day < 15))) (тогда и сюжет выглядит лучше). Тем не менее, принцип все еще отлично работает! - person user3017048; 14.02.2018
comment
Спасибо @ user3017048, я обновил рисунок и код состояния. - person jhamman; 14.02.2018