2015-03-14 15 views
5

Tôi muốn chọn các phần tử nhất định của một mảng và thực hiện phép tính trung bình có trọng số dựa trên các giá trị. Tuy nhiên, bằng cách sử dụng một điều kiện lọc, phá hủy cấu trúc ban đầu của mảng. arr có hình dạng (2, 2, 3, 2) được chuyển thành mảng 1 chiều. Điều này là không sử dụng đối với tôi, vì không phải tất cả các yếu tố này cần phải được kết hợp sau này với nhau (nhưng con của chúng). Làm thế nào tôi có thể tránh được việc làm phẳng này?Mất kích thước mảng mờ khi che mặt

>>> arr = np.asarray([ [[[1, 11], [2, 22], [3, 33]], [[4, 44], [5, 55], [6, 66]]], [ [[7, 77], [8, 88], [9, 99]], [[0, 32], [1, 33], [2, 34] ]] ]) 
>>> arr 
array([[[[ 1, 11], 
     [ 2, 22], 
     [ 3, 33]], 

     [[ 4, 44], 
     [ 5, 55], 
     [ 6, 66]]], 


     [[[ 7, 77], 
     [ 8, 88], 
     [ 9, 99]], 

     [[ 0, 32], 
     [ 1, 33], 
     [ 2, 34]]]]) 
>>> arr.shape 
(2, 2, 3, 2) 
>>> arr[arr>3] 
array([11, 22, 33, 4, 44, 5, 55, 6, 66, 7, 77, 8, 88, 9, 99, 32, 33, 
     34]) 
>>> arr[arr>3].shape 
(18,) 
+1

Xây dựng về việc tính toán những gì bạn cần để làm với các giá trị này. Bạn sẽ sử dụng cấu trúc 'arr' như thế nào? – hpaulj

Trả lời

5

Thanh toán numpy.where

http://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html

Để giữ cho chiều cùng bạn sẽ cần một giá trị điền. Trong ví dụ dưới đây tôi sử dụng 0, nhưng bạn cũng có thể sử dụng np.nan

np.where(arr>3, arr, 0) 

lợi nhuận

array([[[[ 0, 11], 
     [ 0, 22], 
     [ 0, 33]], 

     [[ 4, 44], 
     [ 5, 55], 
     [ 6, 66]]], 


     [[[ 7, 77], 
     [ 8, 88], 
     [ 9, 99]], 

     [[ 0, 32], 
     [ 0, 33], 
     [ 0, 34]]]]) 
+0

Đó là những gì tôi đang tìm kiếm. – orange

3

Nhìn vào arr>3:

In [71]: arr>3 
Out[71]: 
array([[[[False, True], 
     [False, True], 
     [False, True]], 

     [[ True, True], 
     [ True, True], 
     [ True, True]]], 


     [[[ True, True], 
     [ True, True], 
     [ True, True]], 

     [[False, True], 
     [False, True], 
     [False, True]]]], dtype=bool) 

arr[arr>3] chọn những yếu tố mà mặt nạ là True. Bạn muốn lựa chọn cấu trúc hoặc hình dạng nào? Phẳng là điều duy nhất có ý nghĩa, phải không? arr chính nó không thay đổi.

Bạn có thể không ra các điều khoản không phù hợp với mặt nạ,

In [84]: arr1=arr.copy() 
In [85]: arr1[arr<=3]=0 
In [86]: arr1 
Out[86]: 
array([[[[ 0, 11], 
     [ 0, 22], 
     [ 0, 33]], 

     [[ 4, 44], 
     [ 5, 55], 
     [ 6, 66]]], 


     [[[ 7, 77], 
     [ 8, 88], 
     [ 9, 99]], 

     [[ 0, 32], 
     [ 0, 33], 
     [ 0, 34]]]]) 

Bây giờ bạn có thể làm tiền cân hoặc trung bình so với kích thước khác nhau.

np.nonzero (hoặc np.where) cũng có thể có ích, đem lại cho bạn các chỉ số của các từ ngữ được lựa chọn:

In [88]: np.nonzero(arr>3) 
Out[88]: 
(array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]), 
array([0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1]), 
array([0, 1, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 1, 2]), 
array([1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1])) 
5

Bạn có thể xem xét sử dụng một np.ma.masked_array để đại diện cho tập hợp con của các yếu tố đáp ứng điều kiện của bạn:

import numpy as np 

arr = np.asarray([[[[1, 11], [2, 22], [3, 33]], 
        [[4, 44], [5, 55], [6, 66]]], 
        [[[7, 77], [8, 88], [9, 99]], 
        [[0, 32], [1, 33], [2, 34]]]]) 

masked_arr = np.ma.masked_less(arr, 3) 

print(masked_arr) 
# [[[[-- 11] 
# [-- 22] 
# [3 33]] 

# [[4 44] 
# [5 55] 
# [6 66]]] 


# [[[7 77] 
# [8 88] 
# [9 99]] 

# [[-- 32] 
# [-- 33] 
# [-- 34]]]] 

Như bạn có thể thấy, mảng mặt nạ vẫn giữ nguyên thứ nguyên ban đầu của nó. Bạn có thể truy cập dữ liệu cơ bản và mặt nạ thông qua các thuộc tính .data.mask tương ứng. Hầu hết các chức năng NumPy sẽ không đưa vào giá trị che giấu tài khoản, ví dụ:

# mean of whole array 
print(arr.mean()) 
# 26.75 

# mean of non-masked elements only 
print(masked_arr.mean()) 
# 33.4736842105 

Kết quả của một hoạt động tố khôn ngoan trên một mảng đeo mặt nạ và một mảng không đeo mặt nạ cũng sẽ giữ gìn các giá trị của mặt nạ:

masked_arrsum = masked_arr + np.random.randn(*arr.shape) 

print(masked_arrsum) 
# [[[[-- 11.359989067421582] 
# [-- 23.249092437269162] 
# [3.326111354088174 32.679132708120726]] 

# [[4.289134334263137 43.38559221094378] 
# [6.028063054523145 53.5043991898567] 
# [7.44695154979811 65.56890530368757]]] 


# [[[8.45692625294376 77.36860675985407] 
# [5.915835159196378 87.28574554110307] 
# [8.251106168209688 98.7621940026713]] 

# [[-- 33.24398289945855] 
# [-- 33.411941757624284] 
# [-- 34.964817895873715]]]] 

tổng chỉ tính trên giá trị phi đeo mặt nạ của masked_arr - bạn có thể thấy điều này bằng cách nhìn vào masked_sum.data:

print(masked_sum.data) 
# [[[[ 1.   11.35998907] 
# [ 2.   23.24909244] 
# [ 3.32611135 32.67913271]] 

# [[ 4.28913433 43.38559221] 
# [ 6.02806305 53.50439919] 
# [ 7.44695155 65.5689053 ]]] 


# [[[ 8.45692625 77.36860676] 
# [ 5.91583516 87.28574554] 
# [ 8.25110617 98.762194 ]] 

# [[ 0.   33.2439829 ] 
# [ 1.   33.41194176] 
# [ 2.   34.9648179 ]]]] 
+0

Thú vị. Tôi nghĩ rằng 'arr [arr <3]' sẽ ngầm tạo ra một mảng mặt nạ - đã học được một cái gì đó mới (+1). – orange

+1

Hãy nhớ rằng 'arr <3' chỉ là một mảng boolean và việc lập chỉ mục với một mảng boolean sẽ luôn trả về các phần tử đó trong' arr', trong đó chỉ mục boolean là 'True'. Trong sự tò mò, tại sao bạn chọn để đi với 'np.where' cuối cùng? Trong số ba câu trả lời có vẻ như là cách trực tiếp ít nhất để đạt được những gì bạn đang theo đuổi. –

+0

Tôi đã ném lên giữa của bạn và 'np.where'. Tôi đã đi với nó bởi vì nó phù hợp với mục đích trong một dòng mã. Nó có vẻ thích hợp nhất. Tất cả đều là câu trả lời hay ... – orange

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