2010-04-23 74 views
10

Tôi có một mảng có hai cột có dạng khối. Ví dụ:loại bỏ các cặp phần tử khỏi mảng có khối u là NaN (hoặc một giá trị khác) trong Python

a = array([[1, 5, nan, 6], 
      [10, 6, 6, nan]]) 
a = transpose(a) 

Tôi muốn lặp một cách hiệu quả thông qua hai cột, một [:, 0] và [:, 1] và loại bỏ bất kỳ cặp đáp ứng một điều kiện nhất định, trong trường hợp này nếu họ là NaN . Cách rõ ràng tôi có thể nghĩ đến là:

new_a = [] 
for val1, val2 in a: 
    if val2 == nan or val2 == nan: 
    new_a.append([val1, val2]) 

Nhưng điều đó có vẻ khó khăn. Phương pháp numpy pythonic của việc này là gì?

cảm ơn.

Trả lời

29

Nếu bạn muốn đi chỉ có các hàng mà không có Nans, đây là biểu hiện bạn cần:

>>> import numpy as np 
>>> a[~np.isnan(a).any(1)] 
array([[ 1., 10.], 
     [ 5., 6.]]) 

Nếu bạn muốn các hàng mà không có một số cụ thể giữa các yếu tố của nó, ví dụ5:

>>> a[~(a == 5).any(1)] 
array([[ 1., 10.], 
     [ NaN, 6.], 
     [ 6., NaN]]) 

Sau đó rõ ràng là tương đương với

>>> a[(a != 5).all(1)] 
array([[ 1., 10.], 
     [ NaN, 6.], 
     [ 6., NaN]]) 

Giải thích: Hãy đầu tiên tạo ra ví dụ đầu vào của bạn

>>> import numpy as np 
>>> a = np.array([[1, 5, np.nan, 6], 
...    [10, 6, 6, np.nan]]).transpose() 
>>> a 
array([[ 1., 10.], 
     [ 5., 6.], 
     [ NaN, 6.], 
     [ 6., NaN]]) 

này xác định yếu tố nào là NAN

>>> np.isnan(a) 
array([[False, False], 
     [False, False], 
     [ True, False], 
     [False, True]], dtype=bool) 

Xác định này mà hàng có bất kỳ yếu tố nào là True

>>> np.isnan(a).any(1) 
array([False, False, True, True], dtype=bool) 

Kể từ khi chúng tôi không muốn này, chúng ta phủ nhận sự biểu hiện cuối cùng:

>>> ~np.isnan(a).any(1) 
array([ True, True, False, False], dtype=bool) 

Và cuối cùng chúng ta sử dụng mảng boolean để chọn các hàng chúng tôi muốn:

>>> a[~np.isnan(a).any(1)] 
array([[ 1., 10.], 
     [ 5., 6.]]) 
+2

+1: Giải thích rõ ràng và hữu ích, và tôi thích ~ np.isnan vì nó mô tả những gì bạn đang làm. – tom10

+0

Thật là một câu trả lời hay – Tjorriemorrie

2

Tôi nghĩ rằng list comprehensions nên làm điều này. Ví dụ:

new_a = [(val1, val2) for (val1, val2) in a if math.isnan(val1) or math.isnan(val2)] 
+2

Bạn thực sự cần thực hiện phép thử như 'val1! = val1' vì' nan == nan' trả về sai. Nhưng +1. –

+0

Tôi đã chỉnh sửa ở trên ... thành thật mà nói, tôi không bao giờ có nhu cầu 'NaN', vì vậy tôi chủ yếu giải quyết các hình thức xây dựng một danh sách. Dựa trên tài liệu ở đây: http://docs.python.org/library/math.html#math.isnan, tôi nghĩ rằng điều này phải hoạt động ... – ig0774

+2

không nên là: ... ở nơi không phải toán học isnan (val1) và không phải math.isnan (val2)? – user248237dfsf

3

Bạn có thể chuyển đổi mảng thành một masked array, và sử dụng compress_rows method:

import numpy as np 
a = np.array([[1, 5, np.nan, 6], 
      [10, 6, 6, np.nan]]) 
a = np.transpose(a) 
print(a) 
# [[ 1. 10.] 
# [ 5. 6.] 
# [ NaN 6.] 
# [ 6. NaN]] 
b=np.ma.compress_rows(np.ma.fix_invalid(a)) 
print(b) 
# [[ 1. 10.] 
# [ 5. 6.]] 
+2

+1: wow! Tôi không thường thấy các mảng mặt nạ đang được sử dụng và đề xuất! Tốt nhất! – EOL

3

Không được làm giảm từ câu trả lời ig0774, mà là hoàn toàn hợp lệ và Pythonic và là trong thực tế theo cách thông thường thực hiện những việc này bằng Python đơn giản, nhưng: hỗ trợ một hệ thống lập chỉ mục boolean cũng có thể thực hiện công việc.

new_a = a[(a==a).all(1)] 

Tôi không chắc chắn cách nào sẽ hiệu quả hơn (hoặc nhanh hơn để thực thi).

Nếu bạn muốn sử dụng điều kiện khác để chọn các hàng, điều này sẽ phải được thay đổi và chính xác như thế nào phụ thuộc vào điều kiện. Nếu đó là một cái gì đó mà có thể được đánh giá đối với từng phần tử mảng một cách độc lập, bạn chỉ có thể thay thế các a==a với các thử nghiệm thích hợp, ví dụ để loại bỏ tất cả các hàng với số lượng lớn hơn 100 bạn có thể làm

new_a = a[(a<=100).all(1)] 

Nhưng nếu bạn cố gắng làm điều gì đó lạ mắt có liên quan đến tất cả các phần tử trong một hàng (như loại bỏ tất cả các hàng có tổng hơn 100), nó có thể phức tạp hơn. Nếu đúng như vậy, tôi có thể thử chỉnh sửa trong một câu trả lời cụ thể hơn nếu bạn muốn chia sẻ điều kiện chính xác của mình.

+0

+1: cho cách tiếp cận được vector hóa. điều này hầu như luôn luôn nhanh hơn và là một trong những lý do chính để sử dụng numpy. – tom10

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