2016-06-16 2 views
5

У меня есть DataFrame, содержащий временные ряды:GroupBy с TimeGrouper 'назад'

rng = pd.date_range('2016-06-01', periods=24*7, freq='H') 
ones = pd.Series([1]*24*7, rng) 
rdf = pd.DataFrame({'a': ones}) 

Последняя запись 2016-06-07 23:00:00. Теперь я хочу, чтобы сгруппировать это с помощью, скажем, через два дня, в основном, как так:

rdf.groupby(pd.TimeGrouper('2D')).sum() 

Однако, я хочу, чтобы группа, начиная с моих последних точки данных в обратном направлении, поэтому вместо того, чтобы этот результат:

  a 
2016-06-01 48 
2016-06-03 48 
2016-06-05 48 
2016-06-07 24 

я бы предпочел ожидать, что это:

  a 
2016-06-01 24 
2016-06-03 48 
2016-06-05 48 
2016-06-07 48 

и при группировке по '3D':

  a 
2016-06-01 24 
2016-06-04 72 
2016-06-07 72 

Ожидаемые результаты при группировке по '4D' является:

  a 
2016-06-03 72 
2016-06-07 96 

Я не могу получить это с каждой комбинации closed, label и т.д. Я мог думать.

Как я могу это достичь?

ответ

0

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

from pandas.tseries.offsets import Week 

# Let's not make full weeks 
hours = 24*6*4 
rng = pd.date_range('2016-06-01', periods=hours, freq='H') 

# Set week start to whatever the last weekday of the range is 
print("Last day is %s" % rng[-1]) 
freq = Week(weekday=rng[-1].weekday()) 

ones = pd.Series([1]*hours, rng) 
rdf = pd.DataFrame({'a': ones}) 
rdf.groupby(pd.TimeGrouper(freq=freq, closed='right', label='right')).sum() 

Это дает мне нужный выход

2016-06-25 96 
2016-07-02 168 
2016-07-09 168 
+0

Это возможно, возможно, более общее с '' 'DateOffset'''. – TomTom101

0

Поскольку вопрос в настоящее время сосредоточена на группировке по неделям, вы можете просто:

rdf.resample('W-{}'.format(rdf.index[-1].strftime('%a')), closed='right', label='right').sum() 

Вы можете использовать loffset, чтобы заставить его работать - по крайней мере, для большинства периодов (с использованием .resample()):

for i in range(2, 7): 
    print(i) 
    print(rdf.resample('{}D'.format(i), closed='right', loffset='{}D'.format(i)).sum()) 

2 
      a 
2016-06-01 24 
2016-06-03 48 
2016-06-05 48 
2016-06-07 48 
3 
      a 
2016-06-01 24 
2016-06-04 72 
2016-06-07 72 
4 
      a 
2016-06-01 24 
2016-06-05 96 
2016-06-09 48 
5 
       a 
2016-06-01 24 
2016-06-06 120 
2016-06-11 24 
6 
       a 
2016-06-01 24 
2016-06-07 144 

Однако вы также можете создать пользовательские группировки, которые вычисляют правильные значения без TimeGrouper, как показано ниже:

days = rdf.index.to_series().dt.day.unique()[::-1] 
for n in range(2, 7): 
    chunks = [days[i:i + n] for i in range(0, len(days), n)][::-1] 
    grp = pd.Series({k: v for d in [zip(chunk, [idx] * len(chunk)) for idx, chunk in enumerate(chunks)] for k, v in d}) 
    rdf.groupby(rdf.index.to_series().dt.day.map(grp))['a'].sum() 

2 
groups 
0 24 
1 48 
2 48 
3 48 
Name: a, dtype: int64 

3 
groups 
0 24 
1 72 
2 72 
Name: a, dtype: int64 

4 
groups 
0 72 
1 96 
Name: a, dtype: int64 

5 
groups 
0  48 
1 120 
Name: a, dtype: int64 

6 
groups 
0  24 
1 144 
Name: a, dtype: int64 
+0

Благодаря! Поскольку последний бит является моим самым важным, мне нужно, чтобы это было очень надежным. Странно, что, похоже, для этого нет простого решения для лица. – TomTom101

+0

См. Обновленное решение для надежного расчета значений группы, но не использование TimeGrouper. – Stefan

+0

Это заслуживает признания;) Спасибо! – TomTom101

Смежные вопросы