2016-08-25 2 views
0

Мне нужно изменить часть замаскированного массива внутри функции, например:питон - изменить часть замаскированного массива внутри функции

import numpy.ma as ma 

arr_2d = ma.masked_all((5,5)) 
arr_3d = ma.masked_all((5,5,5)) 
arr_3d[0,1] = 5 

def func1(arr, val): 
    arr[:] = val 

выглядит достаточно просто, но потом ...

>>> func1(arr_3d[0], 1) 
>>> arr_3d[0] 
masked_array(data = 
[[-- -- -- -- --] 
[1.0 1.0 1.0 1.0 1.0] 
[-- -- -- -- --] 
[-- -- -- -- --] 
[-- -- -- -- --]], 
      mask = 
[[ True True True True True] 
[False False False False False] 
[ True True True True True] 
[ True True True True True] 
[ True True True True True]], 
     fill_value = 1e+20) 

похоже, что это связано с тем, что общая маска всегда устанавливается на срез массива, так что маска передается функции как копия

Я надеюсь, что может быть какой-то способ исправить или обойти ее флористика r, чем явно пропускать маску, возвращая копию данных или передавая большой массив с индексом.

+0

Неужели вам лучше не возвращать 'arr' из' func1', а затем делать 'arr_3d [0] = func1 (arr_3d [0], 1)'? –

+0

Какое поведение вы хотите? – hpaulj

ответ

0

предупреждение в недавнем NumPy является:

In [738]: func1(A[1],1) 
/usr/local/bin/ipython3:2: MaskedArrayFutureWarning: setting an item on 
a masked array which has a shared mask will not copy the mask and also 
change the original mask array in the future. 
Check the NumPy 1.11 release notes for more information. 

http://docs.scipy.org/doc/numpy/release.html#assigning-to-slices-views-of-maskedarray

В настоящее время кусочек замаскированного массива содержит представление исходных данных и вид копирования при записи из маска. Следовательно, любые изменения в маске среза приведут к копированию оригинальной маски и изменению новой маски, а не оригиналу.

После этого действия строка 1 из A по-прежнему маскируется, но данные A[,:] изменены.

In [757]: B=np.ma.masked_all((5)) 
... 
In [759]: B[0]=5  # direct __setitem__ change to B 
In [760]: B 
Out[760]: 
masked_array(data = [5.0 -- -- -- --], 
      mask = [False True True True True], 
     fill_value = 1e+20) 
In [761]: func1(B[3:],1) 
/usr/local/bin/ipython3:2: MaskedArrayFutureWarning: .... 

In [762]: B  # no change to mask 
Out[762]: 
masked_array(data = [5.0 -- -- -- --], 
      mask = [False True True True True], 
     fill_value = 1e+20) 
In [763]: B.data  # but data is changed 
Out[763]: array([ 5., 0., 0., 1., 1.]) 

A[1,:]=1 является прямым использованием замаскированной __setitem__, и он может принять на себя полную ответственность за установление как data и mask. В вашей функции A - это вид оригинала, полученный при вызове A.__getitem__. Очевидно, разработчики беспокоились о том, должны ли изменения маски этого вида влиять на маску оригинала или нет.

Возможно, нам придется искать обсуждения разработчиков; предупреждение указывает, что в последнее время что-то изменилось.

============

Вопрос не об использовании в функции, речь идет о виде

In [764]: B1=B[3:] 
In [765]: B1[:]=2 
/usr/local/bin/ipython3:1: MaskedArrayFutureWarning:... 
In [766]: B 
Out[766]: 
masked_array(data = [5.0 -- -- -- --], 
      mask = [False True True True True], 
     fill_value = 1e+20) 
In [767]: B.data 
Out[767]: array([ 5., 0., 0., 2., 2.]) 

Предупреждение описывает то, что происходит сейчас, и, возможно, в течение некоторого времени. Это говорит о том, что эта практика изменится.

В соответствии с предложением изменить ноты:

In [785]: B1=B[3:] 
In [787]: B1._sharedmask 
Out[787]: True 
In [790]: B1._sharedmask=False 
In [791]: B1[:]=4 
In [792]: B1 
Out[792]: 
masked_array(data = [4.0 4.0], 
      mask = [False False], 
     fill_value = 1e+20) 
In [793]: B  # mask has been changed along with data 
Out[793]: 
masked_array(data = [5.0 -- -- 4.0 4.0], 
      mask = [False True True False False], 
     fill_value = 1e+20) 

Так меняется

def func1(arr,val): 
    arr._sharedmask=False 
    arr[:]=val 

остановит предупреждение, а также изменять маску исходного массива.

Смежные вопросы