numpy高级特性——掩码数组

640?wx_fmt=jpeg

640?wx_fmt=png

进入正文


一、掩码数组

掩码数组
什么是掩码数组

1.1


1.1.1 什么是掩码数组

640?wx_fmt=other

   

顾名思义,掩码数组也是一种数组,它本质上是对数组的一种特殊处理,一个掩码数组由一个正常数组和一个布尔数组组成,即包含两个数组。掩码的目的就是表明被掩数据的某些位的作用的,通常用来表明被掩数据哪些要处理,哪些不必处理。


1.1.2 掩码数组有什么作用

640?wx_fmt=other

   

对于一个数组而言,数据很有可能是凌乱的,并且含有空白的或者无法处理的字符,或者是不满足要求的数字,掩码式数组可以很好的忽略残缺的或者是无效的数据点。

比如,我们要对一个数组的各个元素求对数,但是元素中含有负数,负数是没有对数的

再比如,我们要对数组的各个列求和,但是有的元素是字符串,而字符串和数字是没办法直接相加的。

出现以上这些情况,我们当然可以通过遍历的方式一个一个排除掉不满足要求的元素,但是这很麻烦,代码冗余,numpy提供的解决思路是使用掩码数组。

掩码式数组由一个正常数组与一个布尔式数组组成,若布尔数组中为Ture,则表示正常数组中对应下标的值无效,反之False表示对应正常数组的值有效。创建方法为,首先创建一个布尔型数组,然后通过numpy.ma子程序包提供的函数来创建掩码式数组,掩码式数组提供了各种所需函数。 后面会讲到。


1.1.3 掩码数组的最初认识

640?wx_fmt=other

   

通过上面的文字描述,我们发现,掩码数组不就是根据每一个元素的true和false决定这个元素是不是有用的吗?我们在使用“布尔索引”的时候其实用到了“掩码”的相类似的思想

x= np.arange(10)

In [44]: x<5 #小于
Out[44]: 
array([ True,  True,  True,  True,  True, False, False, False, False,
       False])

In [45]: x>5 #大于
Out[45]: 
array([False, False, False, False, False, False,  True,  True,  True,
        True])

In [46]: x <= 3 #小于等于
Out[46]: 
array([ True,  True,  True,  True, False, False, False, False, False,
       False])

使用这种方式,每个元素根据相关的条件对应有一个true或者是false,掩码就是利用这种思想去实现的。

Next

二、掩码数组详解

掩码数组详解
创建掩码数组

2.1

640?wx_fmt=other

   

有时候数据集中存在缺失、异常或者无效的数值,我们可以标记该元素为被屏蔽(无效)状态。

numpy.ma模块中提供掩码数组的处理,这个模块中几乎完整复制了numpy中的所有函数,并提供掩码数组的功能;

一个掩码数组由一个正常数组和一个布尔数组组成,布尔数组中值为True的元素表示正常数组中对应下标的值无效,False表示有效;


2.1.1 掩码数组的创建

import numpy.ma as ma
x = np.array([1,2,3,5,7,4,3,2,8,0]) #原始数组
mask = x < 5  #与原始数组对应的不二数组
mx = ma.array(x,mask=mask)

print(mask)

'''array([ True, True, True, False, False, True, True, True, False, True], dtype=bool)'''
print(mx)

'''masked_array(data = [-- -- -- 5 7 -- -- -- 8 --],
mask = [ True True True False False True True True False True],
fill_value = 999999)'''

640?wx_fmt=other

从上面可以看见,掩码数组的创建很简单,与“布尔索引”有密切关联。

掩码数组具有三个属性:data、mask、fill_value;

data表示原始数值数组,

mask表示获得掩码用的布尔数组,

fill_value表示的填充值替代无效值之后的数组,该数组通过filled()方法查看;

掩码数组可以使用各种下标对象对其进行存取,在被掩码的部分值为masked,可以设置某个位置值为ma.masked使其失效;

掩码数组详解
掩码数组的常见操作

2.2

640?wx_fmt=other

掩码数组也是数组,而且是继承自ndarray的数组,故而有很多操作是极其类似的,比如索引、切片等。


2.2.1 访问掩码

这是最简单的操作,即通过mask属性,如下代码

>>> 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.mask  #只访问掩码数组
array([False, False, False,  True, False], dtype=bool)


2.2.2 只访问有效元素

#当只想访问有效数据时,我们可以使用掩码的逆作为索引。可以使用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])


2.2.3 修改掩码

#通过将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)


2.2.4 取消掩码

要取消屏蔽一个或多个特定数据条目,我们只需为它们分配一个或多个新的有效值:

>>> 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)


2.2.5 索引和切片

640?wx_fmt=other

由于MaskedArraynumpy.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
640?wx_fmt=other

如果掩蔽的数组具有命名字段,访问单个条目将返回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')])
640?wx_fmt=other

当访问切片时,输出是掩蔽的数组,其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])

访问具有结构化数据类型的掩蔽数组的字段会返回MaskedArray

本节总结

本届详细介绍了numpy掩码,掩码数组的一些常见操作。

Next


全文总结

掩码数组是numpy的较为高级的特性,虽然平时我们可能用的比较少,但是如果能够灵活应用,可以大大简化我们的代码,提高代码运行效率。

END

往期回顾

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=jpeg

640?wx_fmt=png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值