Pyxis
2018-11-20 19:33

Zwykle gdy przetwarzamy dane, to wygodnie jest operować na tablicach dwuwymiarowych (np. gdy wczytujemy tabele z pliku). Ciekawymi obiektami są tablice maskowane (MaskedArray) w Pythonie. Czasem zachodzi potrzeba zapisania takiego obiektu do pliku. Oczywiście można go zapeklować, ale ja miałem potrzebę zrzucenia takiego obiektu z pominięciem zamaskowanych wierszy. W takim przypadku możemy użyć metody compressed. Problem w tym, że otrzymamy jednowymiarowy obiekt, który burzy nam wielokolumnową strukturę...

Otwórzmy najpierw taki obiekt:

import numpy as np
import numpy.ma as ma

tab = ma.arange(1,36).reshape(7,5)
tab.mask = ~np.asarray(tab, dtype=bool)
tab.mask[2] = tab.mask[5] = True

Wygląda to mniej więcej tak:

masked_array(
  data=[[1, 2, 3, 4, 5],
        [6, 7, 8, 9, 10],
        [--, --, --, --, --],
        [16, 17, 18, 19, 20],
        [21, 22, 23, 24, 25],
        [--, --, --, --, --],
        [31, 32, 33, 34, 35]],
  mask=[[False, False, False, False, False],
        [False, False, False, False, False],
        [ True,  True,  True,  True,  True],
        [False, False, False, False, False],
        [False, False, False, False, False],
        [ True,  True,  True,  True,  True],
        [False, False, False, False, False]],
  fill_value=999999)

Metoda compressed wywołana na tab, czyli tab.compressed() da nam nowy obiekt typu ndarray:

array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 31, 32, 33, 34, 35])

W zasadzie łatwo można to rozwiązać w ten sposób:

tab.data[~tab.mask].reshape(tab.shape[0] - len([_ for i in tab.mask if i.all()]), tab.shape[1])

by dostać:

array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10],
       [16, 17, 18, 19, 20],
       [21, 22, 23, 24, 25],
       [31, 32, 33, 34, 35]])

Po czym możemy zapisać taki obiekt do pliku tekstowego z zachowaniem struktury. tab.data[~tab.mask] zwraca to samo co metoda compressed. W zasadzie główna sprawa to wyznaczenie poprawnego wymiaru macierzy. Stosowanie maskowanej macierzy ma sens, na przykład kiedy chcemy wyróżnić pewną grupę punktów na wykresie. Oczywiście zastosowań jest więcej.