2016-08-09 214 views
2

Ich möchte ein Array aus einem komprimierten maskierten Array und einer entsprechenden Maske erstellen. Sein leichter erklären dies mit einem Beispiel:Invertierung der Operation "numpy.ma.compressed"

>>> x=np.ma.array(np.arange(4).reshape((2,2)), mask = [[True,True],[False,False]]) 
>>> y=x.compressed() 
>>> y 
array([ 2, 3]) 

Jetzt mag ich ein Array in der gleichen Form wie x schaffen, in dem die maskierten Werten einen Standardwert erhalten (zum Beispiel -1) und der Rest wird gefüllt mit ein gegebenes Array. Es sollte so funktionieren:

>>> z = decompress(y, mask=[[True,True],[False,False]], default=-1) 
>>> z 
array([[-1, -1], 
     [ 2, 3]]) 

Die Frage ist: Gibt es eine Methode, wie „dekomprimieren“, oder muss ich es selbst codieren? In Fortran geschieht dies mit den Methoden "packen" und "entpacken". Vielen Dank für Anregungen.

Antwort

3

Während ich eine Anzahl von ma Fragen beantwortet habe, bin ich keineswegs ein Experte damit. Aber ich werde erkunden Sie die Ausgabe

wir verallgemeinern Ihr ein Array ein bisschen:

In [934]: x=np.ma.array(np.arange(6).reshape((2,3)), mask = [[True,True,False],[False,False,True]]) 
In [935]: x 
Out[935]: 
masked_array(data = 
[[-- -- 2] 
[3 4 --]], 
      mask = 
[[ True True False] 
[False False True]], 
     fill_value = 999999) 
In [936]: y=x.compressed() 
In [937]: y 
Out[937]: array([2, 3, 4]) 

y hat keine Informationen über x außer einer Teilmenge von Werten. Hinweis: Es ist 1d

x speichert seine Werte in zwei Arrays (tatsächlich diese Eigenschaften sind, die ._data, ._mask Attribute Zugriff Underlying):

In [938]: x.data 
Out[938]: 
array([[0, 1, 2], 
     [3, 4, 5]]) 
In [939]: x.mask 
Out[939]: 
array([[ True, True, False], 
     [False, False, True]], dtype=bool) 

Meine Vermutung ist, dass zu de-compress wir eine empty maskierte Array vornehmen müssen mit dem richtigen dtype, Form und Maske, und kopieren Sie die Werte von y in seine data. Aber welche Werte sollten in die maskierten Elemente von data eingegeben werden?

Oder eine andere Möglichkeit, das Problem zu stellen - ist es möglich, Werte von y zurück auf x zu kopieren?

Eine mögliche Lösung ist es, die neuen Werte zu x[~x.mask] kopieren:

In [957]: z=2*y 
In [958]: z 
Out[958]: array([4, 6, 8]) 
In [959]: x[~x.mask]=z 
In [960]: x 
Out[960]: 
masked_array(data = 
[[-- -- 4] 
[6 8 --]], 
      mask = 
[[ True True False] 
[False False True]], 
     fill_value = 999999) 
In [961]: x.data 
Out[961]: 
array([[0, 1, 4], 
     [6, 8, 5]]) 

Oder zu machen ein neues Array

In [975]: w=np.zeros_like(x) 
In [976]: w[~w.mask]=y 
In [977]: w 
Out[977]: 
masked_array(data = 
[[-- -- 2] 
[3 4 --]], 
      mask = 
[[ True True False] 
[False False True]], 
     fill_value = 999999) 
In [978]: w.data 
Out[978]: 
array([[0, 0, 2], 
     [3, 4, 0]]) 

Ein weiterer Ansatz ist es, eine regelmäßige Anordnung, full mit den ungültigen Werten Kopieren Sie y wie folgt und verwandeln Sie das Ganze in ein maskiertes Array. Es ist möglich, dass es einen maskierten Array-Konstruktor gibt, mit dem Sie die gültigen Werte nur zusammen mit der Maske angeben können. Aber dafür müsste ich in die Dokumente gehen.

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

Eine weitere Folge von Operationen, die dies tun wird, np.place für Einstellwerte

mit
In [1011]: w=np.empty_like(x) 
In [1014]: np.place(w,w.mask,999) 
In [1015]: np.place(w,~w.mask,[1,2,3]) 
In [1016]: w 
Out[1016]: 
masked_array(data = 
[[-- -- 1] 
[2 3 --]], 
      mask = 
[[ True True False] 
[False False True]], 
     fill_value = 999999) 
In [1017]: w.data 
Out[1017]: 
array([[999, 999, 1], 
     [ 2, 3, 999]]) 

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

Blick auf

https://github.com/numpy/numpy/blob/master/numpy/ma/core.py 
class _MaskedBinaryOperation: 

Diese Klasse zu implementieren maskierte verwendet ufunc.Er wertet die ufunc an gültigen Zellen (nicht maskiert) und gibt einen neuen maskierten Array mit den gültig denjenigen, unverändert die maskierten Werten verlassen (aus dem Original)

Zum Beispiel mit einem einfachen maskierten Array, wird +1 nicht verändert die maskierter Wert.

In [1109]: z=np.ma.masked_equal([1,0,2],0) 
In [1110]: z 
Out[1110]: 
masked_array(data = [1 -- 2], 
      mask = [False True False], 
     fill_value = 0) 
In [1111]: z.data 
Out[1111]: array([1, 0, 2]) 
In [1112]: z+1 
Out[1112]: 
masked_array(data = [2 -- 3], 
      mask = [False True False], 
     fill_value = 0) 
In [1113]: _.data 
Out[1113]: array([2, 0, 3]) 
In [1114]: z.compressed()+1 
Out[1114]: array([2, 3]) 

_MaskedUnaryOperation könnte einfacher sein, zu folgen, da sie nur mit 1 maskierter Array zu arbeiten haben.

Beispiel, hat regelmäßiges Protokoll Probleme mit dem maskierten Wert 0:

In [1115]: z.log() 
... 
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in log 
    #!/usr/bin/python3 
Out[1116]: 
masked_array(data = [0.0 -- 0.6931471805599453], 
      mask = [False True False], 
     fill_value = 0) 

aber das maskierte Protokoll überspringt den maskierten Eintrag:

In [1117]: np.ma.log(z) 
Out[1117]: 
masked_array(data = [0.0 -- 0.6931471805599453], 
      mask = [False True False], 
     fill_value = 0) 
In [1118]: _.data 
Out[1118]: array([ 0.  , 0.  , 0.69314718]) 

oops - _MaskedUnaryOperation nicht so nützlich sein könnte . Es wertet den ufunc bei allen Werten np.ma.getdata(z) mit einem errstate Kontext aus, um Warnungen zu blockieren. Anschließend verwendet er die Maske, um maskierte Werte in das Ergebnis zu kopieren (np.copyto(result, d, where=m)).

+0

Whoa .. das ist eine riesige Ladung an Informationen! Der "np.place" hat es nun geschafft! Danke vielmals! – greeeeeeen