Numpy的布尔索引

假设我们的数据都在数组中,并且数组中的数据是一些存在重复的人名。我们先使用numpy.random中的randn函数来生成一些随机正态分布的数据:

import numpy as np
names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
data = np.random.randn(7,4)

names
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')

data
array([[-0.24427644, -1.46367872, -0.49068242,  1.78822424],
       [-0.86311703,  0.51422326,  0.56743326,  0.8871636 ],
       [-0.5866742 ,  0.73856216,  0.38637554,  0.30568998],
       [ 0.57535788,  1.30374594, -2.05887936, -0.22818597],
       [ 2.35235075,  0.68025456,  1.00348864,  0.32746915],
       [ 0.42857695, -0.16228046,  1.27368772, -0.648772  ],
       [ 0.00398702,  0.72742387, -0.79640429, -0.93247884]])

假设每个人名都和data数组中的一行相对应,并且我们想要选中所有的 ‘Bob’ 对应的行。与数学操作类似,数组的比较操作(比如==)也是可以向量化的。因此,比较names数组和字符串 ‘Bob’ 会产生一个布尔值数组:

names == 'Bob'
array([ True, False, False,  True, False, False, False])

在索引数组时可以传入布尔值数组:

data[names == 'Bob']
array([[-0.24427644, -1.46367872, -0.49068242,  1.78822424],
       [ 0.57535788,  1.30374594, -2.05887936, -0.22818597]])

布尔值数组的长度必须和数组轴索引长度一致。你甚至还可以用切片或整数值对布尔值数组进行混合和匹配。

当布尔值数组的长度不正确时,布尔值选择数据的方法并不会报错,因此我建议在使用该特性的时候要小心。

在这些例子中,我选择 names == ‘Bob’ 的行,并进行索引:

data[names == 'Bob',2:]
array([[-0.49068242,  1.78822424],
       [-2.05887936, -0.22818597]])

data[names == 'Bob',3]
array([ 1.78822424, -0.22818597])

为了选择除了 ‘Bob’ 以外的其他数据,你可以使用 != 或在条件表达式前使用 ~ 对条件取反:

names != 'Bob'
array([False,  True,  True, False,  True,  True,  True])

data[~(names == 'Bob')]
array([[-0.86311703,  0.51422326,  0.56743326,  0.8871636 ],
       [-0.5866742 ,  0.73856216,  0.38637554,  0.30568998],
       [ 2.35235075,  0.68025456,  1.00348864,  0.32746915],
       [ 0.42857695, -0.16228046,  1.27368772, -0.648772  ],
       [ 0.00398702,  0.72742387, -0.79640429, -0.93247884]])

~ 符号可以在你想要对一个通用条件进行取反时使用:

cond = names == 'Bob'

data[~cond]
array([[-0.86311703,  0.51422326,  0.56743326,  0.8871636 ],
       [-0.5866742 ,  0.73856216,  0.38637554,  0.30568998],
       [ 2.35235075,  0.68025456,  1.00348864,  0.32746915],
       [ 0.42857695, -0.16228046,  1.27368772, -0.648772  ],
       [ 0.00398702,  0.72742387, -0.79640429, -0.93247884]])

当要选择三个名字中的两个时,可以对多个布尔值条件进行联合,需要使用数学操作符&(and)和|(or):

mask = (names == 'Bob')|(names == 'Will')

mask
array([ True, False,  True,  True,  True, False, False])

data[mask]
array([[-0.24427644, -1.46367872, -0.49068242,  1.78822424],
       [-0.5866742 ,  0.73856216,  0.38637554,  0.30568998],
       [ 0.57535788,  1.30374594, -2.05887936, -0.22818597],
       [ 2.35235075,  0.68025456,  1.00348864,  0.32746915]])

使用布尔值索引选择数据时,总是生成数据的拷贝,即使返回的数组并没有任何变化。

(Python的关键字and和or对布尔值数组并没有用,请使用&和|来代替。)

基于常识来设置布尔值数组的值也是可行的。将data中所有的负值设置为0,我们需要做:

data[data < 0] = 0

data

data
data
array([[0.        , 0.        , 0.        , 1.78822424],
       [0.        , 0.51422326, 0.56743326, 0.8871636 ],
       [0.        , 0.73856216, 0.38637554, 0.30568998],
       [0.57535788, 1.30374594, 0.        , 0.        ],
       [2.35235075, 0.68025456, 1.00348864, 0.32746915],
       [0.42857695, 0.        , 1.27368772, 0.        ],
       [0.00398702, 0.72742387, 0.        , 0.        ]])

利用一维布尔值数组对每一行设置数值也是非常简单的:

data[names != 'Joe'] = 7

data

data
data
array([[7.00000000e+00, 7.00000000e+00, 7.00000000e+00, 7.00000000e+00],
       [0.00000000e+00, 5.14223265e-01, 5.67433258e-01, 8.87163599e-01],
       [7.00000000e+00, 7.00000000e+00, 7.00000000e+00, 7.00000000e+00],
       [7.00000000e+00, 7.00000000e+00, 7.00000000e+00, 7.00000000e+00],
       [7.00000000e+00, 7.00000000e+00, 7.00000000e+00, 7.00000000e+00],
       [4.28576952e-01, 0.00000000e+00, 1.27368772e+00, 0.00000000e+00],
       [3.98701940e-03, 7.27423872e-01, 0.00000000e+00, 0.00000000e+00]])

猜你喜欢

转载自blog.csdn.net/qq_41205111/article/details/86683370
今日推荐