2011-09-28 39 views
9

Tôi đang cố gắng subsample các hàng của một DataFrame theo một nhóm. Đây là một ví dụ. Nói rằng tôi xác định các dữ liệu sau:Sử dụng gấu trúc, làm thế nào để tôi lấy mẫu một DataFrame lớn theo nhóm một cách hiệu quả?

from pandas import * 
df = DataFrame({'group1' : ["a","b","a","a","b","c","c","c","c", 
          "c","a","a","a","b","b","b","b"], 
       'group2' : [1,2,3,4,1,3,5,6,5,4,1,2,3,4,3,2,1], 
       'value' : ["apple","pear","orange","apple", 
          "banana","durian","lemon","lime", 
          "raspberry","durian","peach","nectarine", 
          "banana","lemon","guava","blackberry","grape"]}) 

Nếu tôi nhóm bởi group1group2, sau đó số lượng hàng trong mỗi nhóm là ở đây:

In [190]: df.groupby(['group1','group2'])['value'].agg({'count':len}) 
Out[190]: 
     count 
a 1 2  
    2 1  
    3 2  
    4 1  
b 1 2  
    2 2  
    3 1  
    4 1  
c 3 1  
    4 1  
    5 2  
    6 1  

(Nếu có một cách thậm chí ngắn gọn hơn để tính toán điều đó, vui lòng cho biết.)

Tôi bây giờ muốn xây dựng một DataFrame có một hàng được chọn ngẫu nhiên từ mỗi nhóm. Đề xuất của tôi là làm như sau:

In [215]: from random import choice 
In [216]: grouped = df.groupby(['group1','group2']) 
In [217]: subsampled = grouped.apply(lambda x: df.reindex(index=[choice(range(len(x)))])) 
In [218]: subsampled.index = range(len(subsampled)) 
In [219]: subsampled 
Out[219]: 
    group1 group2 value 
0 b  2  pear 
1 a  1  apple 
2 b  2  pear 
3 a  1  apple 
4 a  1  apple 
5 a  1  apple 
6 a  1  apple 
7 a  1  apple 
8 a  1  apple 
9 a  1  apple 
10 a  1  apple 
11 a  1  apple 

hoạt động. Tuy nhiên, dữ liệu thực của tôi có khoảng 2,5 triệu hàng và 12 cột. Nếu tôi làm điều này theo cách bẩn thỉu bằng cách xây dựng cấu trúc dữ liệu của riêng mình, tôi có thể hoàn thành thao tác này chỉ trong vài giây. Tuy nhiên, việc triển khai của tôi ở trên không hoàn thành trong vòng 30 phút (và dường như không bị hạn chế về bộ nhớ). Như một lưu ý phụ, khi tôi thử thực hiện điều này trong R, trước tiên tôi đã thử plyr, cũng không hoàn thành trong một khoảng thời gian hợp lý; tuy nhiên, một giải pháp sử dụng data.table hoàn thành rất nhanh.

Làm cách nào để làm việc này hoạt động nhanh chóng với pandas? Tôi muốn yêu gói này, vì vậy hãy giúp đỡ!

Trả lời

8

Tôi đã thử nghiệm với áp dụng, có vẻ như khi có nhiều nhóm phụ, nó rất chậm. thuộc tính nhóm của nhóm là một dict, bạn có thể lựa chọn chỉ số trực tiếp từ nó:

subsampled = df.ix[(choice(x) for x in grouped.groups.itervalues())] 

EDIT: Tính đến phiên bản gấu trúc 0.18.1, itervalues không còn hoạt động trên các đối tượng groupby - bạn có thể chỉ cần sử dụng .values:

subsampled = df.ix[(choice(x) for x in grouped.groups.values())] 
+3

Tôi đã trả lời về danh sách gửi thư về pystatsmodels về việc này. Tôi đã đưa ra cùng một giải pháp mà bạn đề xuất-- là tác giả gói tôi không biết cách nào tốt hơn =) –

+0

@ wesm, tôi vừa mới đăng câu trả lời của bạn ở đây. Cảm ơn mọi người! –

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