Python агрегация двух временных рядов - PullRequest
0 голосов
/ 01 марта 2019

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

        date    value
0 2016-03-21       10
1 2016-03-25       10
2 2016-04-10       10
3 2016-05-05       10

Второй - это диапазон дат с интервалами в 10 календарных дней, извлеченных из вышеуказанного ряда.Я написал код для извлечения этого из вышеуказанных данных.

     date
 0   2016-03-21
 1   2016-03-31
 2   2016-04-10
 3   2016-04-20
 4   2016-04-30

Я хочу написать некоторый код для получения этого результирующего кадра данных:

     date        value
 0   2016-03-21  20
 1   2016-03-31   0
 2   2016-04-10  10
 3   2016-04-20   0
 4   2016-04-30  10

Не могли бы вы предложить способ сделать этобез использования циклов (желательно) в Python?

Ответы [ 3 ]

0 голосов
/ 01 марта 2019

Numpy searchsorted

Это первое, о чем я подумал, но это не было тривиально сгладить.Ответ @ Вайшали по духу очень похож на этот и более простой.Но я как собака с костью и не могу ее отпустить, пока не пойму.

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

x = np.array([*'abdg'])
y = np.array([*'acdef'])

Обратите внимание, что для каждой буквы в x я обнаружил, где обратная остановка была в y

#  i -> 0 0   2     4
#  x -> a b   d     g
#  y -> a   c d e f

Этополучается то, что я делаю ниже.

Настройка

df = pd.DataFrame(dict(
    date=pd.to_datetime(['2016-03-21', '2016-03-25', '2016-04-10', '2016-05-05']),
    value=[10, 10, 10, 10]
))

dates = pd.date_range(df.date.min(), df.date.max(), freq='10D')

Решение

d = df.date.values
v = df.value.values

i = dates.searchsorted(d, side='right') - 1
a = np.zeros(len(dates), dtype=v.dtype)

np.add.at(a, i, v)

pd.DataFrame(dict(
    date=dates, value=a
))

        date  value
0 2016-03-21     20
1 2016-03-31      0
2 2016-04-10     10
3 2016-04-20      0
4 2016-04-30     10

Вы заметите, что я использовал np.add.at для суммирования v только в нужных местах.Я мог бы также сделать это с np.bincount.Мне нравится вышеуказанный подход лучше, потому что np.bincount приводит к float, хотя v имеет тип int.

d = df.date.values
v = df.value.values

i = dates.searchsorted(d, side='right') - 1

pd.DataFrame(dict(
    date=dates, value=np.bincount(i, v).astype(v.dtype)
))

        date  value
0 2016-03-21     20
1 2016-03-31      0
2 2016-04-10     10
3 2016-04-20      0
4 2016-04-30     10
0 голосов
/ 01 марта 2019

Просто успейте добавить мое решение, numpy, вещание

s1=df1.date.values
s2=df2.date.values
a=(np.abs(s1-s2[:,None])/np.timedelta64(60*60*24, 's')<10).dot(df1.value.values)
a
Out[183]: array([20, 10, 10,  0, 10], dtype=int64)

#df2['value']=a
0 голосов
/ 01 марта 2019

Вы можете поместить данные в df1 на основании значений в датах df2,

bins = pd.date_range(df2.date.min(), df2.date.max() + pd.DateOffset(10), freq = '10D')
labels = df2.date
df1.groupby(pd.cut(df1.date, bins = bins, right = False, labels = labels)).value.sum().reset_index()


    date        value
0   2016-03-21  20
1   2016-03-31  0
2   2016-04-10  10
3   2016-04-20  0
4   2016-04-30  10
...