2017-11-03 52 views
5

Tôi có một dataframe gấu trúc với khoảng 150.000.000 hàng trong các định dạng sau:cách hiệu quả nhất để groupby => tổng hợp cho dataframe lớn trong gấu trúc

df.head() 

Out[1]: 
    ID TERM X 
0 1  A  0 
1 1  A  4 
2 1  A  6 
3 1  B  0 
4 1  B  10 
5 2  A  1 
6 2  B  1 
7 2  F  1 

tôi muốn tổng hợp nó bằng ID & HẠN, và đếm số hàng. Hiện tại tôi làm như sau:

df.groupby(['ID','TERM']).count() 

Out[2]: 
    ID TERM X 
0 1  A  3 
1 1  B  2 
2 2  A  1 
3 2  B  1 
4 2  F  1 

Nhưng điều này mất khoảng hai phút. Các hoạt động tương tự bằng cách sử dụng dữ liệu R. có thể mất ít hơn 22 giây. Có cách nào hiệu quả hơn để làm điều này trong python?

Để so sánh, R data.table:

giải pháp
system.time({ df[,.(.N), .(ID, TERM)] }) 
#user: 30.32 system: 2.45 elapsed: 22.88 
+0

Đó có vẻ như là cách tiếp cận đúng. Tôi đã làm một số timings trên 10.000 hàng với kích thước thay vì đếm như @ jezrael gợi ý nhưng điều đó không có vẻ tốt hơn. Tôi đã nghĩ python sẽ nhanh hay nhanh hơn R ở đây nên tôi rất ngạc nhiên. Nhưng thông thường bạn có thể tăng tốc độ của một phương pháp gấu trúc bằng cách viết một hàm numpy hoặc numba tùy chỉnh, vì vậy đó có thể là điều tiếp theo để thử. – JohnE

+0

Ồ, lý do R có thể nhanh hơn ở đây là nếu gấu trúc đánh vào giới hạn bộ nhớ vì gấu trúc không phải lúc nào cũng hiệu quả bộ nhớ thực (và đó có thể là lý do tại sao có thể tăng tốc độ một chút). Trong trường hợp đó, các tùy chọn là thực hiện phép tính theo khối, tìm máy tính có nhiều bộ nhớ hơn, hoặc nhìn vào blaze, dask, vv như @jezrael đề cập đến – JohnE

+1

'TERM' có giữ chuỗi ký tự đơn không? – Divakar

Trả lời

1

Một NumPy sẽ là như vậy -

def groupby_count(df): 
    unq, t = np.unique(df.TERM, return_inverse=1) 
    ids = df.ID.values 
    sidx = np.lexsort([t,ids]) 

    ts = t[sidx] 
    idss = ids[sidx] 

    m0 = (idss[1:] != idss[:-1]) | (ts[1:] != ts[:-1]) 
    m = np.concatenate(([True], m0, [True])) 
    ids_out = idss[m[:-1]] 
    t_out = unq[ts[m[:-1]]] 
    x_out = np.diff(np.flatnonzero(m)+1) 

    out_ar = np.column_stack((ids_out, t_out, x_out)) 
    return pd.DataFrame(out_ar, columns = [['ID','TERM','X']]) 

đơn giản Một chút phiên bản -

def groupby_count_v2(df):  
    a = df.values 
    sidx = np.lexsort(a[:,:2].T) 
    b = a[sidx,:2] 
    m = np.concatenate(([True],(b[1:] != b[:-1]).any(1),[True])) 
    out_ar = np.column_stack((b[m[:-1],:2], np.diff(np.flatnonzero(m)+1))) 
    return pd.DataFrame(out_ar, columns = [['ID','TERM','X']]) 

mẫu chạy -

In [332]: df 
Out[332]: 
    ID TERM X 
0 1 A 0 
1 1 A 4 
2 1 A 6 
3 1 B 0 
4 1 B 10 
5 2 A 1 
6 2 B 1 
7 2 F 1 

In [333]: groupby_count(df) 
Out[333]: 
    ID TERM X 
0 1 A 3 
1 1 B 2 
2 2 A 1 
3 2 B 1 
4 2 F 1 

Hãy xáo trộn ngẫu nhiên các hàng và xác minh rằng nó hoạt động với giải pháp của chúng tôi -

In [339]: df1 = df.iloc[np.random.permutation(len(df))] 

In [340]: df1 
Out[340]: 
    ID TERM X 
7 2 F 1 
6 2 B 1 
0 1 A 0 
3 1 B 0 
5 2 A 1 
2 1 A 6 
1 1 A 4 
4 1 B 10 

In [341]: groupby_count(df1) 
Out[341]: 
    ID TERM X 
0 1 A 3 
1 1 B 2 
2 2 A 1 
3 2 B 1 
4 2 F 1 
+0

Điều này nhanh và tránh hết bộ nhớ, cảm ơn! –

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