2015-01-09 18 views
5

Tôi có một dữ liệu lớn thiết lập với cơ cấu như sauLàm thế nào để đặt một khung dữ liệu bằng cách sử dụng Pandas dựa trên tiêu chí nhóm?

User  X 
1  0 
1  0 
2  0 
2  0 
2  1 
3  0 
3  0 

Tôi muốn để có một tập hợp con của dữ liệu như vậy mà tổng của cột X cho mỗi người dùng được 0. Với ví dụ trên, tập hợp con nên chỉ bao gồm các quan sát cho người dùng 1 và 3 như sau

User  X 
1  0 
1  0 
3  0 
3  0 

Có cách nào để thực hiện việc này bằng cách sử dụng chức năng nhóm không có nhóm dữ liệu? Tôi muốn tập hợp con bao gồm các quan sát riêng lẻ.

+0

Chúng ta biết rằng tất cả 'X' là> = 0, hay bạn cần phải lo lắng về' -1, + 1'? – DSM

+0

tất cả các giá trị X là> = 0 – roland

Trả lời

5

DSM's answer, chọn hàng bằng mặt nạ boolean, hoạt động tốt ngay cả khi DataFrame có chỉ mục không phải duy nhất. Phương pháp của tôi, chọn hàng bằng cách sử dụng giá trị chỉ mục, hơi chậm hơn khi chỉ mục là duy nhất và chậm hơn đáng kể khi chỉ mục chứa giá trị trùng lặp.

@roland: Thay vào đó, hãy xem xét chấp nhận câu trả lời của DSM.


Bạn có thể sử dụng một groupby-filter:

In [16]: df.loc[df.groupby('User')['X'].filter(lambda x: x.sum() == 0).index] 
Out[16]: 
    User X 
0  1 0 
1  1 0 
5  3 0 
6  3 0 

Bằng cách riêng của mình, các groupby lọc chỉ trả về này:

In [29]: df.groupby('User')['X'].filter(lambda x: x.sum() == 0) 
Out[29]: 
0 0 
1 0 
5 0 
6 0 
Name: X, dtype: int64 

nhưng sau đó bạn có thể sử dụng chỉ số của nó,

In [30]: df.groupby('User')['X'].filter(lambda x: x.sum() == 0).index 
Out[30]: Int64Index([0, 1, 5, 6], dtype='int64') 

để chọn các hàng mong muốn bằng cách sử dụng df.loc.


Dưới đây là điểm chuẩn tôi đã sử dụng:

In [49]: df2 = pd.concat([df]*10000) # df2 has a non-unique index 

tôi Ctrl - C 'd này vì nó được dùng quá lâu để hoàn thành:

In [50]: %timeit df2.loc[df2.groupby('User')['X'].filter(lambda x: x.sum() == 0).index] 

Khi Tôi nhận ra sai lầm của mình, tôi đã tạo một DataFrame với một chỉ mục duy nhất:

In [51]: df3 = df2.reset_index()  # this gives df3 a unique index 

In [52]: %timeit df3.loc[df3.groupby('User')['X'].filter(lambda x: x.sum() == 0).index] 
100 loops, best of 3: 13 ms per loop 

In [53]: %timeit df3.loc[df3.groupby("User")["X"].transform(sum) == 0] 
100 loops, best of 3: 11.4 ms per loop 

Điều này cho thấy phương pháp DSM của hoạt động tốt ngay cả với một chỉ số không duy nhất:

In [54]: %timeit df2.loc[df2.groupby("User")["X"].transform(sum) == 0] 
100 loops, best of 3: 11.2 ms per loop 
8

Để thay thế cho câu trả lời @ unutbu của, cũng có

>>> df.loc[df.groupby("User")["X"].transform(sum) == 0] 
    User X 
0  1 0 
1  1 0 
5  3 0 
6  3 0 

Điều này tạo ra một boolean Chiều dài df Loạt để sử dụng làm công cụ chọn:

>>> df.groupby("User")["X"].transform(sum) == 0 
0  True 
1  True 
2 False 
3 False 
4 False 
5  True 
6  True 
dtype: bool 

transform được sử dụng khi bạn muốn "phát sóng" kết quả của một hoạt động giảm nhóm lại cho tất cả các thành phần của mỗi nhóm. Nó có ích.

+0

bạn có thể thực hiện yêu cầu kéo để thêm giá trị này vào sách dạy nấu ăn không? (có thể cho phần SQL) - đây là cơ bản có tuyên bố – Jeff

+0

Đây là một câu trả lời tốt hơn đáng kể so với tôi vì nó hoạt động tốt ngay cả khi DataFrame có một chỉ mục không duy nhất. Phương pháp của tôi có thể khá chậm trong trường hợp đó. Việc chọn với một mặt nạ boolean đầy đủ sẽ mạnh hơn việc chọn bằng các giá trị chỉ mục. – unutbu

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