2012-07-10 2 views
47

Tôi muốn lọc các hàng theo hàm của mỗi hàng, ví dụ:gấu trúc: bộ lọc phức tạp trên các hàng của DataFrame

def f(row): 
    return sin(row['velocity'])/np.prod(['masses']) > 5 

df = pandas.DataFrame(...) 
filtered = df[apply_to_all_rows(df, f)] 

Hoặc thêm phức tạp hơn, ví dụ contrived,

def g(row): 
    if row['col1'].method1() == 1: 
    val = row['col1'].method2()/row['col1'].method3(row['col3'], row['col4']) 
    else: 
    val = row['col2'].method5(row['col6']) 
    return np.sin(val) 

df = pandas.DataFrame(...) 
filtered = df[apply_to_all_rows(df, g)] 

Làm thế nào tôi có thể làm như vậy?

Trả lời

70

Bạn có thể thực hiện việc này bằng cách sử dụng DataFrame.apply, whic h áp dụng một hàm dọc theo một trục nhất định,

In [3]: df = pandas.DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c']) 

In [4]: df 
Out[4]: 
      a   b   c 
0 -0.001968 -1.877945 -1.515674 
1 -0.540628 0.793913 -0.983315 
2 -1.313574 1.946410 0.826350 
3 0.015763 -0.267860 -2.228350 
4 0.563111 1.195459 0.343168 

In [6]: df[df.apply(lambda x: x['b'] > x['c'], axis=1)] 
Out[6]: 
      a   b   c 
1 -0.540628 0.793913 -0.983315 
2 -1.313574 1.946410 0.826350 
3 0.015763 -0.267860 -2.228350 
4 0.563111 1.195459 0.343168 
+1

Không cần phải áp dụng 'trong trường hợp này. Một chỉ số boolean thông thường sẽ hoạt động tốt. 'df [df ['b]> df [' c ']]'. Có rất ít tình huống thực sự yêu cầu 'áp dụng' và thậm chí một vài trường hợp cần nó với' axis = 1' –

8

Giả sử tôi đã có một DataFrame như sau:

In [39]: df 
Out[39]: 
     mass1  mass2 velocity 
0 1.461711 -0.404452 0.722502 
1 -2.169377 1.131037 0.232047 
2 0.009450 -0.868753 0.598470 
3 0.602463 0.299249 0.474564 
4 -0.675339 -0.816702 0.799289 

tôi có thể sử dụng tội lỗi và DataFrame.prod để tạo ra một mặt nạ boolean:

In [40]: mask = (np.sin(df.velocity)/df.ix[:, 0:2].prod(axis=1)) > 0 

In [41]: mask 
Out[41]: 
0 False 
1 False 
2 False 
3  True 
4  True 

Sau đó sử dụng mặt nạ để chọn từ DataFrame :

In [42]: df[mask] 
Out[42]: 
     mass1  mass2 velocity 
3 0.602463 0.299249 0.474564 
4 -0.675339 -0.816702 0.799289 
+2

thực sự, điều này có lẽ là một ví dụ xấu: 'np.sin' tự động chương trình phát sóng đến tất cả các yếu tố này. Điều gì sẽ xảy ra nếu tôi thay thế nó bằng một chức năng ít thông minh hơn mà chỉ có thể xử lý một đầu vào tại một thời điểm? – duckworthd

1

10 Tôi có thể bình luận trên duckworthd's answer, nhưng nó không hoạt động hoàn hảo. Nó bị treo khi dataframe trống:

df = pandas.DataFrame(columns=['a', 'b', 'c']) 
df[df.apply(lambda x: x['b'] > x['c'], axis=1)] 

Đầu ra:

ValueError: Must pass DataFrame with boolean values only 

Đối với tôi nó trông giống như một lỗi trong gấu trúc, vì {} dứt khoát là một tập hợp lệ của các giá trị boolean.