numpy.ma详解
numpy.ma
numpy.ma模塊
基本原理
當數組元素包括缺失值或異常值時,該數組被稱為掩碼數組。numpy.ma模塊的工作方式可以這么來解釋:支持數值數組中包含掩碼元素。
什么是掩碼數組呢?
在很多情況下,數據集可能是不完整或存在無效數據的。例如,一個傳感器對于某個數值可能有以下兩種存儲情況:存儲失敗、存入一個無效數據。numpy.ma模塊通過引入掩碼數組,為這種問題的解決提供了一種便捷的方法。
掩碼數組是將標準的多維數組numpy.ndarray和掩碼相結合。掩碼要么是nomask,表示與該掩碼有關數組的所有值都是有效的。要么是一個布爾值數組,用于確定關聯數組的每個元素值是否有效。當掩碼中某個元素值為False,那么關聯數組的對應元素是有效的,即被認為是未掩碼的。當掩碼中某個元素值為True,那么關聯數組的對應元素是無效的,即被認為是掩碼的。
這個包可以確保掩碼項不參與計算。
為了讓大家有一個直觀的認識,我們給出下例:
我們想要將x數組中第四個值標記為無效數據。最便捷的方法是創建一個掩碼數組:
mx = ma.masked_array(x, mask=[0, 0, 0, 1, 0])現在,我們可以在不考慮-1這個異常值的情況下,計算數組x的均值:
print('僅僅計算[1, 2, 3, 5]的均值,計算結果為:{}'.format(mx.mean()))僅僅計算[1, 2, 3, 5]的均值,計算結果為:2.75
numpy.ma模塊
numpy.ma模塊最主要的特性是掩碼數組MaskedArray類,該類是多維數組numpy.ndarray的子類。掩碼數組的屬性以及方法詳見MaskedArray class。
numpy.ma模塊可以當作numpy包的補充:
我們可以這樣子創建一個第二個元素無效的數組:
y = ma.array([1, 2, 3], mask = [0, 1, 0])我們可以創建一個掩碼數組,其中所有接近1.e20的值都是無效的:
z = ma.masked_values([1.0, 1.e20, 3.0, 4.0], 1.e20)更多創建掩碼數組的方法詳見Constructing masked arrays。
使用numpy.ma
構建掩碼數組
有如下幾種方法來創建掩碼數組。
- 第一種方式是直接調用MaskedArray類。
- 第二種方式是使用兩種掩碼數組構造函數,array和masked_array。
- array(data[, dtype, copy, order, mask, …]): 定義了掩碼值的數組類
- masked_array: 和MaskedArray一樣
- 第三種方式是獲取現有數組的視圖。在這種情況下,如果數組沒有命名字段,或者沒有與數組結構相同的布爾數組,則將視圖的掩碼設置為nomask。
masked_array(data=[1, 2, 3],
mask=False,
fill_value=999999)
masked_array(data=[(1, 1.0), (2, 2.0)],
mask=[(False, False), (False, False)],
fill_value=(999999, 1.e+20),
dtype=[(‘a’, ‘<i4’), (‘b’, ‘<f8’)])
- 以下函數也可以創建掩碼數組:
| asarray(a[, dtype, order]) | 基于給定的數值類型將輸入數據轉換為掩碼數組 |
| asanyarray(a[, dtype]) | 不改變子類的前提下,將輸入數據轉換為掩碼數組 |
| fix_invalid(a[, mask, copy, fill_value]) | 將輸入數組中的無效元素用填充值進行替代 |
| masked_equal(x, value[, copy]) | 對數組中等于value的值進行掩碼操作 |
| masked_greater(x, value[, copy]) | 對數組中大于value的值進行掩碼操作 |
| masked_greater_equal(x, value[, copy]) | 對數組中大于等于value的值進行掩碼操作 |
| masked_inside(x, v1, v2[, copy]) | 對數組中落在給定區間的值進行掩碼操作 |
| masked_invalid(a[, copy]) | 對數組中無效數據(例如NaN或inf)進行掩碼操作 |
| masked_less(x, value[, copy]) | 對數組中小于value的值進行掩碼操作 |
| masked_less_equal(x, value[, copy]) | 對數組中小于等于value的值進行掩碼操作 |
| masked_not_equal(x, value[, copy]) | 對數組中不等于value的值進行掩碼操作 |
| masked_object(x, value[, copy, shrink]) | 對數組(元素為’cats’等對象)中等于value的值進行掩碼操作 |
| masked_outside(x, v1, v2[, copy]) | 對數組中落在給定區間之外的值進行掩碼操作 |
| masked_values(x, value[, rtol, atol, copy, …]) | 被掩碼部分替換為-- |
| masked_where(condition, a[, copy]) | 對數組中滿足條件的部分進行掩碼操作 |
訪問數據
掩碼數組的底層數據可以通過以下方式進行訪問:
- 通過data屬性。輸出是數組的視圖,該數組的類型取決于掩碼數組創建時的底層數據類型,可能為numpy.ndarray或其子類。
- 通過__array__方法。輸出為多維數組numpy.ndarray。
- 直接將掩碼數組的視圖視為多維數組numpy.ndarray或其子類之一(實際上是使用data屬性來完成)。
- 通過使用getdata函數。
如果某些項被標已經被標記為無效,那么這些方法的結果都差強人意。有一個通用規則,如果需要一個沒有任何掩碼項的數組表示,建議使用填充filled的方法填充數組。
訪問掩碼
掩碼數組可以通過其mask屬性獲取掩碼。我們必須記住掩碼中的True表示無效數據。使用getmask和getmaskarray函數也可以獲取到掩碼。如果x為掩碼數組getmask(x)將返回x的掩碼,否則返回nomask。如果x為掩碼數組getmaskarray(x)將返回x的掩碼。如果x沒有無效值或者其不為掩碼數組,該函數返回len(x)個False組成的布爾型數組。
僅獲取有效值
為了檢索數組中的有效值,我們可以使用掩碼取反作為索引。掩碼取反操作可以使用函數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])
備注:compressed的返回值通常為1維。
修改掩碼
屏蔽一個條目
將一個掩碼數組中的一個或多個特定項標記為無效的推薦方法是將掩碼值masked賦給它們:
x = ma.array([1, 2, 3]) x[0] = ma.masked xmasked_array(data=[–, 2, 3],
mask=[ True, False, False],
fill_value=999999)
masked_array(
data=[[1, --, 3],
[4, 5, --],
[–, 8, 9]],
mask=[[False, True, False],
[False, False, True],
[ True, False, False]],
fill_value=999999)
masked_array(data=[–, --, 3, 4],
mask=[ True, True, False, False],
fill_value=999999)
另外一種方法就是使用mask直接修改掩碼,但是這種方法已經被廢除了。
注意:
當使用簡單的,非結構化的數據類型創建新的掩碼數組時,掩碼會被初始化為nomask,相當于布爾值序列全為False。
一個數組中的所有元素可以一并設置其掩碼為True:
masked_array(data=[–, --, --],
mask=[ True, True, True],
fill_value=999999,
dtype=int32)
可以通過對布爾值序列進行賦值來確定數組中的哪些元素用掩碼表示:
x = ma.array([1, 2, 3]) x.mask = [0, 1, 0] xmasked_array(data=[1, --, 3],
mask=[False, True, False],
fill_value=999999)
對屏蔽條目解除屏蔽
我們可以通過對屏蔽條目賦予新的有效值來解除其屏蔽:
x = ma.array([1, 2, 3], mask=[0, 0, 1]) xmasked_array(data=[1, 2, --],
mask=[False, False, True],
fill_value=999999)
masked_array(data=[1, 2, 5],
mask=[False, False, False],
fill_value=999999)
注意:
當掩碼數組屬性為hard mask時,可能不能有效地對其解除屏蔽。這個特性是為了防止用戶對掩碼值進行覆蓋。要想取消數組的hard_mask屬性,必須在解除屏蔽前先對其利用soften_mask方法進行軟化。當然,修改完畢之后也可以使用harden_mask屬性防止掩碼部分被修改:
masked_array(data=[1, 2, --],
mask=[False, False, True],
fill_value=999999)
masked_array(data=[1, 2, --],
mask=[False, False, True],
fill_value=999999)
masked_array(data=[1, 2, 5],
mask=[False, False, False],
fill_value=999999)
masked_array(data=[1, 2, --],
mask=[False, False, True],
fill_value=999999)
對掩碼數組(非hard mask)所有屏蔽部分解屏蔽的最簡單方法是給mask賦常數nomask:
x = ma.array([1, 2, 3], mask=[0, 0, 1]) xmasked_array(data=[1, 2, --],
mask=[False, False, True],
fill_value=999999)
masked_array(data=[1, 2, 3],
mask=[False, False, False],
fill_value=999999)
索引和切片
由于掩碼數組MaskedArray是多維數組numpy.ndarray的子類,所以它繼承了索引和切片的機制。
當獲取一個沒有命名空間的掩碼數組的單一元素時,輸出值既不是標量(如果掩碼的對應項為False)也不是特殊值masked(如果掩碼的對應項為True):
1
x[-1]masked
x[-1] is ma.maskedTrue
如果掩碼數組有命名空間,則從中獲取一個元素和多維數組的返回機制相同:
(1, 2)
y[-1](3, --)
當從掩碼數組中獲取一個切片時,其返回值仍然是掩碼數組,并且為原數組的一個視圖。返回數組的mask既不是nomask(如果原始數組中沒有無效數據),也不是原始數組mask的一個副本。所以在切片時最好做深拷貝,以防止對切片數據修改的同時也修改了原始數組。
masked_array(data=[1, --, 3],
mask=[False, True, False],
fill_value=999999)
masked_array(data=[1, -1, 3],
mask=[False, False, False],
fill_value=999999)
array([False, False, False, False, True])
x.dataarray([ 1, -1, 3, 4, 5])
使用結構化數據類型訪問掩碼數組的字段將返回一個掩碼數組MaskedArray。
對掩碼數組進行操作
掩碼數組支持數學運算和邏輯運算。掩碼數組中的無效數據將不參與運算,這意味著相應的數據項在操作前后應該不會發生改變。
注意:
我們應該強調掩碼部分不發生改變的特性不是掩碼數組自帶的屬性,在一些情況下掩碼數值有可能在運算的過程中發生改變,所以用戶不應該在運算過程中將掩碼數值不變當作一個假設。
numpy.ma支持大多數的數學運算。對于一些有特定定義域的函數(例如log、divide),當運算結果為無效值時,返回masked常數:
masked_array(data=[–, --, 0.0, 0.6931471805599453],
mask=[ True, True, False, False],
fill_value=1e+20)
掩碼數組也支持標準的numpy函數,輸出為掩碼數組。當函數的輸入值被屏蔽時,函數不會對該部分進行計算。當輸入值超出了函數的定義域,函數會返回掩碼值:
x = ma.array([-1, 1, 0, 2, 3], mask=[0, 0, 0, 0, 1]) np.log(x)masked_array(data=[–, 0.0, --, 0.6931471805599453, --],
mask=[ True, False, True, False, True],
fill_value=1e+20)
示例
利用特殊值表示缺失值
現在有一個列表x,其中用-9999.表示缺失值。我們想要計算這些數值的平均數并對其進行均值分析(每個值距離均值的偏差):
import numpy.ma as ma x = [0.,1.,-9999.,3.,4.] mx = ma.masked_values (x, -9999.) print('掩碼數組的均值為:{}'.format(mx.mean())) print('每個值與均值的差值為:{}'.format(mx - mx.mean())) print('每個值與均值的差值為:{}'.format(mx.anom()))掩碼數組的均值為:2.0
每個值與均值的差值為:[-2.0 -1.0 – 1.0 2.0]
每個值與均值的差值為:[-2.0 -1.0 – 1.0 2.0]
對缺失值進行填充
假設我們現在相對上一個數組進行打印,其中缺失值以均值進行替代。
print('用均值填充缺失值后的結果:{}'.format(mx.filled(mx.mean())))用均值填充缺失值后的結果:[0. 1. 2. 3. 4.]
數值計算
在掩碼數組中,我們無需擔心缺失值便可進行數值計算,例如分母為0,對復數求平方根等等:
import numpy as np, numpy.ma as ma x = ma.array([1., -1., 3., 4., 5., 6.], mask=[0,0,0,0,1,0]) y = ma.array([1., 2., 0., 4., 5., 6.], mask=[0,0,0,0,0,1]) print(np.sqrt(x/y))[1.0 – -- 1.0 – --]
輸出結果中有四個值為無效值,第一個是因為對負數取平方根,第二個是因為除0,最后兩個是因為輸入值被掩碼。
忽略極端值
假設我們有一個數組d,其元素為0到1之間隨機的浮點數。我們想對其[0.1, 0.9]區間范圍內的值取平均:
d = np.random.random(size=100) print(ma.masked_outside(d, 0.1, 0.9).mean())0.46533658283140283
github鏈接
https://github.com/wzy6642/numpy-translate
總結
以上是生活随笔為你收集整理的numpy.ma详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: numpy.concatenate详解
- 下一篇: numpy.dstack详解