2012-12-21 27 views
20

Tôi có đối tượng chuỗi thời gian grouped của loại <pandas.core.groupby.SeriesGroupBy object at 0x03F1A9F0>. grouped.sum() cho kết quả mong muốn nhưng tôi không thể nhận được rolling_sum để làm việc với đối tượng groupby. Có cách nào để áp dụng các chức năng cán cho các đối tượng groupby không? Ví dụ:Python - chức năng cán cho đối tượng GroupBy

x = range(0, 6) 
id = ['a', 'a', 'a', 'b', 'b', 'b'] 
df = DataFrame(zip(id, x), columns = ['id', 'x']) 
df.groupby('id').sum() 
id x 
a 3 
b 12 

Tuy nhiên, tôi muốn có một cái gì đó như:

id x 
0 a 0 
1 a 1 
2 a 3 
3 b 3 
4 b 7 
5 b 12 
+0

Làm thế nào để bạn mong đợi chức năng cuộn hoạt động trên các đối tượng được nhóm (ý tôi là viết ra phép tính y) bạn muốn làm trong các biểu tượng)? – tacaswell

+0

Xin lỗi tôi nên rõ ràng hơn. – ezbentley

+0

Vì vậy, bạn muốn làm một 'cumsum' trên mỗi nhóm và sau đó khâu toàn bộ điều trở lại vào một khung dữ liệu duy nhất? – tacaswell

Trả lời

25
In [16]: df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1) 
Out[16]: 
0 0.0 
1 0.5 
2 1.5 
3 3.0 
4 3.5 
5 4.5 

In [17]: df.groupby('id')['x'].cumsum() 
Out[17]: 
0  0 
1  1 
2  3 
3  3 
4  7 
5 12 
+8

pd.rolling_mean hiện không được chấp nhận cho Series và sẽ bị xóa, sử dụng 'df.groupby ('id') ['x']. Rolling (2) .mean()' thay vì – kekert

1

Tôi không chắc chắn của các cơ chế, nhưng hoạt động này. Lưu ý, giá trị trả về chỉ là một ndarray. Tôi nghĩ rằng bạn có thể áp dụng bất kỳ chức năng tích lũy hoặc "cán" theo cách này và nó sẽ có kết quả tương tự.

Tôi đã thử nghiệm nó với cumprod, cummaxcummin và tất cả đều trả về một biến thể. Tôi nghĩ gấu trúc là đủ thông minh để biết rằng các hàm này trả về một chuỗi và do đó hàm được áp dụng như một phép biến đổi chứ không phải là một tập hợp.

In [35]: df.groupby('id')['x'].cumsum() 
Out[35]: 
0  0 
1  1 
2  3 
3  3 
4  7 
5 12 

Edit: Tôi tìm thấy nó tò mò rằng cú pháp này không trả về một Series:

In [54]: df.groupby('id')['x'].transform('cumsum') 
Out[54]: 
0  0 
1  1 
2  3 
3  3 
4  7 
5 12 
Name: x 
22

Đối với các chuyên gia của Google đến khi câu hỏi cũ:

Về @ kekert của bình luận trên Câu trả lời của @ Garrett để sử dụng số điện thoại mới

df.groupby('id')['x'].rolling(2).mean() 

chứ không phải là bây giờ bị phản đối

df.groupby('id')['x'].apply(pd.rolling_mean, 2, min_periods=1) 

tò mò, có vẻ như rằng .rolling mới(). Nghĩa là() phương pháp trả về một loạt đa lập chỉ mục, lập chỉ mục bởi các cột group_by đầu tiên và sau đó chỉ số. Trong khi đó, cách tiếp cận cũ sẽ đơn giản trả về một chuỗi được lập chỉ mục một cách độc lập bởi chỉ mục df ban đầu, điều này có lẽ ít ý nghĩa hơn, nhưng rất thuận tiện cho việc thêm chuỗi đó làm cột mới vào khung dữ liệu ban đầu.

Vì vậy, tôi nghĩ rằng tôi đã tìm ra một giải pháp mà sử dụng phương pháp lăn mới() và vẫn hoạt động giống nhau:

df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True) 

mà nên cung cấp cho bạn hàng loạt

0 0.0 
1 0.5 
2 1.5 
3 3.0 
4 3.5 
5 4.5 

mà bạn có thể thêm dưới dạng cột:

df['x'] = df.groupby('id')['x'].rolling(2).mean().reset_index(0,drop=True) 
+0

Tôi nghĩ bạn có thể sử dụng '.transform' thay vì reset_index? – TMrtSmith

+1

Điều này thực sự không thành công nếu bạn nhóm theo nhiều cột. Việc bỏ qua đối số đầu tiên (các cấp) sẽ giải quyết điều này mặc dù nó loại bỏ tất cả các cấp theo mặc định. Vì vậy, dòng trở thành 'df ['x'] = df.groupby ('id') ['x']. Rolling (2) .mean(). Reset_index (drop = True)' –

Các vấn đề liên quan