2015-06-03 17 views
6

Tôi đang cố tạo cột trên khung dữ liệu chứa tối thiểu cột A (cột giá trị), cột B (id) cột) có một giá trị cụ thể. Mã của tôi rất chậm. Tôi đang tìm cách nhanh hơn để làm điều này. Đây là chức năng nhỏ của tôi:Cách nhanh nhất để tìm hàm tính toán trên lát DataFrame theo giá trị cột (pandas Python)

def apply_by_id_value(df, id_col="id_col", val_col="val_col", offset_col="offset", f=min): 
    for rid in set(df[id_col].values): 
     df.loc[df[id_col] == rid, offset_col] = f(df[df[id_col] == rid][val_col]) 
    return df 

Và ví dụ sử dụng:

import pandas as pd 
import numpy as np 
# create data frame 
df = pd.DataFrame({"id_col":[0, 0, 0, 1, 1, 1, 2, 2, 2], 
        "val_col":[0.1, 0.2, 0.3, 0.6, 0.4, 0.5, 0.2, 0.1, 0.0]}) 

print df.head(10) 
# output 
    id_col val_col 
0  0  0.1 
1  0  0.2 
2  0  0.3 
3  1  0.6 
4  1  0.4 
5  1  0.5 
6  2  0.2 
7  2  0.1 
8  2  0.0 

df = apply_by_id_value(df) 
print df.head(10) 
# output 

    id_col val_col offset 
0  0  0.1  0.1 
1  0  0.2  0.1 
2  0  0.3  0.1 
3  1  0.6  0.4 
4  1  0.4  0.4 
5  1  0.5  0.4 
6  2  0.2  0.0 
7  2  0.1  0.0 
8  2  0.0  0.0 

Một số bối cảnh nhiều hơn: Trong dữ liệu thực tế của tôi, "id_col" cột có một số 30000 hoặc độc đáo hơn giá trị. Điều này có nghĩa là khung dữ liệu phải được cắt 30000 lần. Tôi tưởng tượng đây là nút cổ chai.

Trả lời

5

Thực hiện một groupby vào 'id_col' và sau đó một transform qua chức năng 'min', điều này sẽ trả về một dòng liên kết để df ban đầu của bạn, do đó bạn có thể thêm một cột mới:

In [13]: 

df = pd.DataFrame({"id_col":[0, 0, 0, 1, 1, 1, 2, 2, 2], 
        "val_col":[0.1, 0.2, 0.3, 0.6, 0.4, 0.5, 0.2, 0.1, 0.0]}) 
df['offset'] = df.groupby('id_col').transform('min') 
df 
Out[13]: 
    id_col val_col offset 
0  0  0.1  0.1 
1  0  0.2  0.1 
2  0  0.3  0.1 
3  1  0.6  0.4 
4  1  0.4  0.4 
5  1  0.5  0.4 
6  2  0.2  0.0 
7  2  0.1  0.0 
8  2  0.0  0.0 

timings

In [15]: 

def apply_by_id_value(df, id_col="id_col", val_col="val_col", offset_col="offset", f=min): 
    for rid in set(df[id_col].values): 
     df.loc[df[id_col] == rid, offset_col] = f(df[df[id_col] == rid][val_col]) 
    return df 
%timeit apply_by_id_value(df) 
%timeit df.groupby('id_col').transform('min') 
100 loops, best of 3: 8.12 ms per loop 
100 loops, best of 3: 5.99 ms per loop 

vì vậy, các groupbytransform là nhanh hơn trên tập dữ liệu này, tôi hy vọng nó sẽ được đáng kể nhanh hơn trên dữ liệu thực sự của bạn vì nó sẽ mở rộng quy mô tốt hơn.

Đối với một hàng 800.000 df tôi nhận được timings sau:.

1 loops, best of 3: 611 ms per loop 
1 loops, best of 3: 438 ms per loop 
+1

Các groupby() transform() Giải pháp là "chỉ" khoảng 1.000 lần nhanh hơn trong các dữ liệu thực ;-) Cảm ơn rất nhiều! Tôi biết nó đã có trong API, một nơi nào đó. – nikosd

+0

Tôi đoán nó phụ thuộc vào việc phân phối dữ liệu, trên tập dữ liệu của bạn chỉ có 3 giá trị duy nhất, vì vậy, thậm chí ghép lại chính nó lên 100.000 lần thời gian tra cứu vẫn tương đối nhanh hơn, nhưng trên tập dữ liệu đa dạng hơn, tốc độ tăng lên đáng kể cho tôi biết sự khác biệt tăng tốc – EdChum

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