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 数组强大功能以及它的灵活性,对于上述操作方法需要大家实际去练习然后再掌握它们。注意当我们再使用布尔值索引选择数据时,生成的是数据的拷贝,即不会影响到原数组数据。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/24094.html