Numpy花式索引,你都会了吗?

Numpy索引和切片

Numpy数组的索引使用方法非常丰富,因为选取数据子集或单个元素的方式有很多。

Numpy一维数组功能从表面上看和Python的列表差不多。

array = np.arange(10)
array
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
array[5:7]
array([5, 6])
array[5:7] = 10
array
array([ 0,  1,  2,  3,  4, 10, 10,  7,  8,  9])

如上所示,如果将一个标量值赋值给一个切片时,即array[5:7]=10,该值会自动传播给数组的整个选区。

对于Numpy数组而言,数组切片均为原始数组的视图,也就是说当你对切片进行操作的时候,视图上的修改都直接反映到源数据。如果你想要得到数组切片的一份副本,则需要使用.copy()函数。

Numpy的切片主要应用在高维数组上比较多。

对于一个二维数组,第一个索引位置是对应的一维数组:

array2 = [np.arange(5),np.arange(5)]
array2
array2
[array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4])]
array2[1]
array([0, 1, 2, 3, 4])
array2[1][3]
3

如上,在多维数组中,如果你省略了后面的索引,那么返回对象是一个低维度的数组。

array3 = np.array([[[1,2],[3,4]],[[5,6],[7,8]]])
y3
array3
array([[[1, 2],
        [3, 4]],
       [[5, 6],
        [7, 8]]])
array3[0]
array([[1, 2],
       [3, 4]])

标量和数组都可以传递给上例中的array3[0]

array3[0] = 5
array3[1] = array3[0].copy()
array3
array3
array([[[5, 5],
        [5, 5]],
       [[5, 5],
        [5, 5]]])

上例中先赋值给array3[0]数5,然后赋值给array3[1]array3[0]的副本。

对于高纬度的ndarray,你可以在一个或多个轴上进行切片,也可以跟整数索引混合使用。

array4
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
array4[:2]
array([[1, 2, 3],
       [4, 5, 6]])
array4[:2,1:]
array([[2, 3],
       [5, 6]])
array4[2][1:]
array([8, 9])

相信看了上面几个实例,应该掌握了ndarray区域切片的方法。既可以使用轴(冒号)切片,也可以与整数索引混合使用,通过配合使用,你可以选定ndarray里面的任何相邻区域元素。

布尔型索引

现在有一个ndarray如下:

name
array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype=')

你可以使用==运算符得到一个布尔型数组:

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

得到的这个布尔型数组可以用作数组索引:

data
array([[-0.97133348, -0.5600425 , -0.79953394],
       [-0.16137989,  0.64255114, -0.23057695],
       [ 0.46766496,  0.4166806 ,  1.89590574],
       [ 0.20037889,  1.24162949, -1.22615282],
       [ 0.04411636, -0.10187134, -2.87967816],
       [-1.12559886,  1.37114668,  1.05111639],
       [ 2.80698643,  0.67018108,  1.67296472]])
data[name == 'Bob']
array([[-0.97133348, -0.5600425 , -0.79953394],
       [ 0.20037889,  1.24162949, -1.22615282]])

注意,利用上面布尔型数组作为索引即返回的True的那些行。

另外需要注意的是,在Numpy中如果想要进行逻辑操作需要使用&(和)、|(或),Python里面的andor关键字在Numpy中无效:

test = (name == 'Bob')|(name == 'Will')
test
test
array([ True, False,  True,  True,  True, False, False])

test = (name == 'Bob') or (name == 'Will')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-52-debf1f9c9f26> in <module>
----> 1 test = (name == 'Bob') or (name == 'Will')

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

布尔型数组最主要的作用是给数组赋值,如下示例:

data
array([[ 1.88490696, -1.21508243,  0.45033942],
       [-1.8350759 , -0.11018609, -0.89959447],
       [-0.04100068,  0.74753441, -0.32248567],
       [ 0.24694001, -0.57307637, -0.62334876],
       [-0.43501341,  0.541733  , -1.91950243]])
 = 100
data[data<0] = 100
data
data
array([[  1.88490696, 100.        ,   0.45033942],
       [100.        , 100.        , 100.        ],
       [100.        ,   0.74753441, 100.        ],
       [  0.24694001, 100.        , 100.        ],
       [100.        ,   0.541733  , 100.        ]])

花式索引

花式索引(Fancy indexing)是一个Numpy术语,它指的是利用整数数组进行索引。例如:

array5
array([[0., 0., 0., 0.],
       [1., 1., 1., 1.],
       [2., 2., 2., 2.],
       [3., 3., 3., 3.],
       [4., 4., 4., 4.],
       [5., 5., 5., 5.],
       [6., 6., 6., 6.],
       [7., 7., 7., 7.]])
array5[[1,3,5,7]]
array([[1., 1., 1., 1.],
       [3., 3., 3., 3.],
       [5., 5., 5., 5.],
       [7., 7., 7., 7.]])

另外你也可以使用负整数,如果使用负整数,那么索引会从末尾倒着开始:

array5[[-1,-3,-5,-7]]
array([[7., 7., 7., 7.],
       [5., 5., 5., 5.],
       [3., 3., 3., 3.],
       [1., 1., 1., 1.]])

你还可以传入多个整数数组,它返回的是一个一维数组,其中的元素对应各个索引元组:

array6
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27]])
array6[[1,3,5],[0,2,3]]
array([ 4, 14, 23])

能看明白上面操作发生了什么吗?

数组转置和轴对换

转置transpose是重塑的一种特殊形式,它返回的是源数据的视图。数组不仅有transpose方法,还有一个特殊的T属性:

array6
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23],
       [24, 25, 26, 27]])
array6.T
array6.T
array([[ 0,  4,  8, 12, 16, 20, 24],
       [ 1,  5,  9, 13, 17, 21, 25],
       [ 2,  6, 10, 14, 18, 22, 26],
       [ 3,  7, 11, 15, 19, 23, 27]])

如果你需要计算矩阵的内积 X T X X^TX XTX

np.dot(array6.T,array6)
array([[1456, 1540, 1624, 1708],
       [1540, 1631, 1722, 1813],
       [1624, 1722, 1820, 1918],
       [1708, 1813, 1918, 2023]])

对于高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置:

array7
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],
       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])
array7.transpose((1,0,2))
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],
       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

复杂的转置一般用transpose函数,简单的就用.T

一些通用函数

通用函数是对一种ndarray中的数据执行元素级运算的函数。

一元函数
函数 说明
abs、fabs 计算整数、浮点数或复数的绝对值。对于非复数值,可以使用更快的fabs
sqrt 计算各元素的平方根
square 计算各元素的平方
exp 计算各元素的指数 e x e^x ex
log、log10、log2、log1p 分别为自然对数、底数为10、2的对数和log(1+x)
sign 计算各元素的正负号,1为正,-1为负,0即0
ceil 计算大于等于该值的最小整数
floor 计算小于等于该值的最大整数
rint 将各元素四舍五入到最近的整数,dtype不变
modf 将数组小数和整数部分以两个独立数组的形式返回
isnan 返回一个表示哪些值是NaN的布尔型数组
isfinite、isinf 返回一个表示哪些元素是有穷的(非inf,非NaN)或无穷的布尔型数组
cos、cosh、sin、sinh、tan、tanh 普通型和双曲型三角函数
二元函数
函数 说明
add 将数组中对应的元素相加
subtract 从第一个数组中减去第二个数组中的元素
multiply 数组元素相乘
divide、floor_divide 除法或向下圆整除法(丢弃余数)
power 对一个数组中的元素A根据第二个数组中的元素B,计算 A B A^B AB
maximum、fmax 元素级的最大值计算。fmax将忽略NaN
minimum、fmin 元素级的最小值i计算。fmin将忽略NaN
mod 元素级的求模运算(除法的余数)
copysign 将第二个数组中的值的符号复制给第一个数组中的值
greater、greater_equal、less、less_equal、equal、not_equal 执行元素级的比较运算,最终产生布尔型数组相当于> >= < <= == !=
logical_and、logical_or、logical_xor 执行元素级的真值逻辑运算。相当于中缀运算符& | ^

你可能感兴趣的:(数据分析入门,1024程序员节,python,numpy,索引)