2016-06-16 15 views
5

Tôi có một DataFrame chứa một chuỗi thời gian:groupby với TimeGrouper 'ngược'

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

entry cuối là 2016-06-07 23:00:00. bây giờ tôi muốn nhóm này bằng cách, nói hai ngày, về cơ bản giống như vậy:

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

Tuy nhiên, tôi muốn nhóm bắt đầu từ dữ liệu cuối cùng của tôi điểm ngược, vì vậy thay vì nhận được kết quả này:

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

tôi muốn có nhiều thay mong đợi điều này:

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

và khi nhóm bởi '3D':

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

kết quả mong đợi khi nhóm bởi '4D' là:

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

Tôi không thể có được điều này với tất cả sự kết hợp của closed, label vv Tôi có thể nghĩ đến.

Tôi làm cách nào để đạt được điều này?

Trả lời

0

Kể từ khi tôi chủ yếu muốn nhóm của 7 ngày, hay còn gọi là một tuần, tôi đang sử dụng phương pháp này ngay bây giờ để đến thùng mong muốn:

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() 

này mang lại cho tôi những kết quả mong muốn của

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

Điều này có thể được thực hiện rộng rãi hơn với '' 'DateOffset'''. – TomTom101

0

Kể từ khi câu hỏi bây giờ tập trung vào nhóm theo tuần, bạn có thể chỉ đơn giản là:

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

Bạn có thể sử dụng loffset để làm cho nó làm việc - ít nhất là đối với hầu hết các giai đoạn (sử dụng .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 

Tuy nhiên, bạn cũng có thể tạo các nhóm tùy chỉnh tính toán các giá trị chính xác mà không cần TimeGrouper như sau:

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

Cảm ơn! Vì thùng cuối cùng là cái quan trọng nhất của tôi, tôi cần cái này rất đáng tin cậy. Lạ thật, có vẻ như không có giải pháp dễ dàng đối mặt với vấn đề này. – TomTom101

+0

Xem cập nhật cho giải pháp để tính giá trị nhóm theo cách đáng tin cậy nhưng không sử dụng TimeGrouper. – Stefan

+0

Nó xứng đáng được chấp nhận;) Cảm ơn! – TomTom101