1. 程式人生 > >Numpy 修煉之道 (11)—— 掩碼陣列

Numpy 修煉之道 (11)—— 掩碼陣列

有時候資料集中存在缺失、異常或者無效的數值,我們可以標記該元素為被遮蔽(無效)狀態。
>>> import numpy as np
>>> import numpy.ma as ma
>>> x = np.array([1, 2, 3, -99, 5])
>>> x
array([  1,   2,   3, -99,   5])
現在可以創造一個掩碼陣列(標記第四個元素為無效狀態)。
>>> mx = ma.masked_array(x, mask=[0,
0, 0, 1, 0])
>>> mx
masked_array(data = [1 2 3 -- 5],
mask = [False False False True False],
fill_value = 999999)
接下來可以計算平均值而不用考慮無效資料。
>>> mx.mean()
2.75

   訪問掩碼

可通過其mask屬性訪問掩碼陣列的掩碼。我們必須記住,掩碼中的True條目表示無效資料。
>>> mx
masked_array(data = [1 2 3 -- 5],
mask = [False False False  True False],
      fill_value = 999999)
>>> mx.mask
array([False, False, False,  True, False], dtype=bool)

   只訪問有效資料

當只想訪問有效資料時,我們可以使用掩碼的逆作為索引。可以使用numpy.logical_not函式或簡單使用~運算子計算掩碼的逆:
>>> x = ma.array([[1, 2], [3, 4]],
mask=[[0, 1], [1, 0]])
>>> x[~x.mask]
masked_array(data = [1 4],
mask = [False False],
  fill_value = 999999)
另一種檢索有效資料的方法是使用compressed方法,該方法返回一維ndarray(或其子類之一,取決於baseclass屬性):
>>> x.compressed()
array([1, 4])

   修改掩碼

通過將True賦給掩碼,可以立即遮蔽陣列的所有資料:
>>> x = ma.array([1, 2, 3], mask=[0,0, 1])
>>> x.mask = True
>>> x
masked_array(data = [-- -- --],
  mask = [ True  True  True],
    fill_value = 999999)
最後,可以通過向掩碼分配一系列布林值來對特定資料條目進行掩碼和/或取消掩碼:
>>> x = ma.array([1, 2, 3])
>>> x.mask = [0, 1, 0]
>>> x
masked_array(data = [1 -- 3],
 mask = [False  True False],
      fill_value = 999999)

   取消掩碼

要取消遮蔽一個或多個特定資料條目,我們只需為它們分配一個或多個新的有效值:
>>> x = ma.array([1, 2, 3], mask=[0,0, 1])
>>> x
masked_array(data = [1 2 --],
 mask = [False False  True],
      fill_value = 999999)
>>> x[-1] = 5
>>> x
masked_array(data = [1 2 5],
 mask = [False False False],
      fill_value = 999999)
要取消遮蔽掩碼陣列的所有掩碼條目(假設掩碼不是硬掩碼),最簡單的解決方案是將常量nomask分配給掩碼:
>>> x = ma.array([1, 2, 3], mask=[0,0, 1])
>>> x
masked_array(data = [1 2 --],
 mask = [False False  True],
      fill_value = 999999)
>>> x.mask = ma.nomask
>>> x
masked_array(data = [1 2 3],
 mask = [False False False],
      fill_value = 999999)

   索引和切片

由於MaskedArray是numpy.ndarray的子類,它會繼承其用於索引和切片的機制。
當訪問沒有命名欄位的被掩蔽陣列的單個條目時,輸出是標量(如果掩碼的相應條目是False)或特殊值masked (如果掩碼的相應條目為True):
>>> x = ma.array([1, 2, 3], mask=[0,0, 1])
>>> x[0]
1
>>> x[-1]
masked_array(data = --,
 mask = True,
      fill_value = 1e+20)
>>> x[-1] is ma.masked
True
如果掩蔽的陣列具有命名欄位,訪問單個條目將返回numpy.void物件(如果沒有掩碼),或者如果至少一個欄位具有與初始陣列相同的dtype的0d掩碼陣列的欄位被遮蔽。
>>> y = ma.masked_array([(1,2), (3,4)],
...           
   mask=[(0, 0), (0, 1)],
...           
  dtype=[('a', int), ('b', int)])
>>> y[0]
(1, 2)
>>> y[-1]
masked_array(data = (3, --),
 mask = (False, True),
      fill_value = (999999,999999),
dtype = [('a', '<i4'), ('b', '<i4')])
當訪問切片時,輸出是掩蔽的陣列,其data屬性是原始資料的檢視,並且其掩碼是nomask(如果沒有無效條目原始陣列)或原始掩碼的相應切片的副本。需要複製以避免將掩模的任何修改傳播到原始版本。
>>> x = ma.array([1, 2, 3, 4, 5],
mask=[0, 1, 0, 0, 1])
>>> mx = x[:3]
>>> mx
masked_array(data = [1 -- 3],
 mask = [False  True False],
      fill_value = 999999)
>>> mx[1] = -1
>>> mx
masked_array(data = [1 -1 3],
 mask = [False  True False],
      fill_value = 999999)
>>> x.mask
array([False,  True, False, False,  True], dtype=bool)
>>> x.data
array([ 1, -1,  3,  4,  5])



腦洞科技棧專注於人工智慧與量化投資領域


瞭解更多幹貨文章,關注小程式八斗問答