首页 > 编程笔记 > Python笔记

Numpy布尔索引掩码操作详解

本节我们讲解 Numpy 数组的布尔索引操作,大家对于这一概念很可能会无感,通过本节知识的介绍,你会认识到 Numpy 数组的与众不同的。Numpy 数组布尔索引也可以叫做掩码操作,即通过一组布尔值序列,对 Numpy 数组进行取值操作,下面就正式进入本节的主要内容。

1. 简单的数组掩码操作

布尔值即 True 或 False 使用它们两者进行索引可以使 Numpy 数组呈现出我们想要的数据,我们先看一个简单的示例:
In [1]: import numpy as np
In [2]: data=np.arange(1,11)
#创建mask掩码布尔值列表
In [3]: mask=[True,False,True,False,True,False,True,False,True,False]
#使用布尔值对数组data进行索引
In [4]: data[mask]
#输出只有奇数的数组
Out[4]: array([1, 3, 5, 7, 9])
通过上面的代码,你应该对布尔值索引有了一个基本的认识。这种使用 mask 布尔值序列对数组进行取值的操作,称之为掩码,即掩盖掉不想显示的数据。下面我们讲一些实际的应用场景。

2. 数组掩码实际应用

假设现在有一组班级姓名的数组,并且还有一组成绩表,成绩表我们可以随机生成一组数据,如下所示:
In [1]: import numpy as np

In [2]: data=np.arange(1,11)

In [3]: mask=[True,False,True,False,True,False,True,False,True,False]

In [4]: data[mask]
Out[4]: array([1, 3, 5, 7, 9])

In [5]: import numpy as np
#名字数组
In [6]: names=np.array(['xm','ls','cd','ra','xm','lz'])
#随机生成6行4列的成绩数组并和姓名一一对应
In [7]: data=np.random.randn(6,4)
In [8]: data
Out[8]:
array([[ 0.11862692,  0.43370356,  0.24572782,  0.12563666],
       [-0.66938338, -0.27592135,  0.27299139, -0.62841077],
       [-0.49116108, -1.34173789,  1.71092549,  0.97037571],
       [ 0.79156476, -0.33761401,  0.15094182,  0.59195507],
       [-0.10606347,  0.00604084, -0.3119981 , -0.82903705],
       [ 1.2775524 , -0.76599632, -1.41684961,  0.27957322]])

In [9]: names
Out[9]: array(['xm', 'ls', 'cd', 'ra', 'xm', 'lz'], dtype='<U2')
我们假设每个人名都和 data 数组的一行数据相对应,如果此时我们想要根据名字筛选出我们想要的成绩应该怎么做呢?我们知道 True 和 False 可以用来判断一个 if 表达式的条件是否成立,若成立则返回 True,否则就返回 False,所以在此处依然使用这种思想来考虑。

我们使用数学上的比较运算符就可以得到想要的结果,如下所示:
In [1]: import numpy as np

In [2]: names=np.array(['xm','ls','cd','ra','xm','lz'])

In [3]: data=np.random.randn(6,4)

In [4]: names
Out[4]: array(['xm', 'ls', 'cd', 'ra', 'xm', 'lz'], dtype='<U2')

In [5]: data
Out[5]:
array([[ 1.27893324, -0.2869719 ,  1.53727143,  0.92759443],
       [-1.34825698,  0.61118769,  0.09381353, -0.25670181],
       [ 1.23828121, -0.60258588, -1.29633343, -0.79827614],
       [-0.69281436,  0.35496869, -1.18819669, -1.06783884],
       [-0.63522862, -0.46742291,  1.29312452, -1.83039843],
       [ 1.0572994 ,  1.55526538,  0.46449384, -0.2587228 ]])
#使names数组等于xm会生成布尔序列数组
In [6]: names=="xm"
#为xm的位置显示为True
Out[6]: array([ True, False, False, False,  True, False])
#对data数组进行掩码操作 
In [7]: data[names=="xm"]
#输入结果为xm对应的行数
Out[7]:
array([[ 1.27893324, -0.2869719 ,  1.53727143,  0.92759443],
       [-0.63522862, -0.46742291,  1.29312452, -1.83039843]])
这里有一点需要大家注意,布尔值数组长度必须和数组索引长度一致。继续上面示例,我们还可以使用如下的方式,父获取的数组结果进一步操作:
In [8]: data[names=="xm"]
Out[8]:
array([[ 1.27893324, -0.2869719 ,  1.53727143,  0.92759443],
       [-0.63522862, -0.46742291,  1.29312452, -1.83039843]])
#前面的位置代表选择行,后面表示选择列
In [9]: data[names=="xm",3]
Out[9]: array([ 0.92759443, -1.83039843])

In [10]: data[names=="xm",-2]
Out[10]: array([1.53727143, 1.29312452])

In [11]: data[names=="xm",1:]
Out[11]:
array([[-0.2869719 ,  1.53727143,  0.92759443],
       [-0.46742291,  1.29312452, -1.83039843]])
data[names=="xm",1:] 表示 data 对应names=='xm' 的行,列取值不包含第一列以外的所有列。

3. 掩码的其他使用方法

1) 使用 | 和 &生成布尔值索引

理解了上面的使用方法后,我们再来看看其他使用方法,我们也可以使用逻辑运算符号 | 和 & 来进行布尔值索引,它们分别代表着 or 和 and,在布尔值中需要使用符号来代替关键字,如下所示:
In [19]: mask=(names=="xm")|(names=="ls")
In [20]: mask
Out[20]: array([ True,  True, False, False,  True, False])
In [21]: mask=(names=="xm")&(names=="ls")
In [22]: mask
Out[22]: array([False, False, False, False, False, False])

2) 使用 !=和~进行掩码操作

使用不相等和取反也可以进行掩码操作,如下所示,它们最终的结果是一样的:
In [12]: names!="xm"
Out[12]: array([False,  True,  True,  True, False,  True])

In [13]: data[names!="xm"]
Out[13]:
array([[-1.34825698,  0.61118769,  0.09381353, -0.25670181],
       [ 1.23828121, -0.60258588, -1.29633343, -0.79827614],
       [-0.69281436,  0.35496869, -1.18819669, -1.06783884],
       [ 1.0572994 ,  1.55526538,  0.46449384, -0.2587228 ]])

In [14]: data[~(names=="xm")]
Out[14]:
array([[-1.34825698,  0.61118769,  0.09381353, -0.25670181],
       [ 1.23828121, -0.60258588, -1.29633343, -0.79827614],
       [-0.69281436,  0.35496869, -1.18819669, -1.06783884],
       [ 1.0572994 ,  1.55526538,  0.46449384, -0.2587228 ]])

3) 使用数学比较号生成布尔值

我们可以使用数学上的比较符号对数组值进行判断,进而操作数组中数值,比如重新赋值等:
In [23]: data<0
#data<0生成布尔值数组
Out[23]:
array([[False,  True, False, False],
       [ True, False, False,  True],
       [False,  True,  True,  True],
       [ True, False,  True,  True],
       [ True,  True, False,  True],
       [False, False, False,  True]])
In [24]: data[data<0]=0
#对于满足条件的数值进行修改去掉负值
In [25]: data
Out[25]:
array([[1.27893324, 0.        , 1.53727143, 0.92759443],
       [0.        , 0.61118769, 0.09381353, 0.        ],
       [1.23828121, 0.        , 0.        , 0.        ],
       [0.        , 0.35496869, 0.        , 0.        ],
       [0.        , 0.        , 1.29312452, 0.        ],
       [1.0572994 , 1.55526538, 0.46449384, 0.        ]])
In [26]: data[names!='lz']=7
#对于满足条件的数据进行修改
In [27]: data
Out[27]:
array([[7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [1.0572994 , 1.55526538, 0.46449384, 0.        ]])
通过上面的示例,我们可以看出 Numpy 数组强大功能以及它的灵活性,对于上述操作方法需要大家实际去练习然后再掌握它们。注意当我们再使用布尔值索引选择数据时,生成的是数据的拷贝,即不会影响到原数组数据。

所有教程

优秀文章