Python学习笔记(2):Numpy基础之数组运算及索引和切片
2019-02-07 本文已影响1人
刘爱玛
目录
一、数组运算
二、数组索引和切片
1、切片索引
(1)一维数组
(2)二维数组
2、布尔型索引
3、花式索引
一、数组运算
本章主要讨论大小相同的数组运算(大小不同的数组运算又叫做广播,在后面章节介绍)。
数组之间的运算都会被应用到元素级。
示例:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
arr*arr
输出:
array([[ 1, 4, 9],
[16, 25, 36]])
arr-arr
输出:
array([[0, 0, 0],
[0, 0, 0]])
1/arr
输出:
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
arr ** 0.5
输出:
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
二、数组索引和切片
1、切片索引
这里有一点与Java、C++等语言有明显不同,数组切片是原始数组的视图,这意味着数据不会被复制,视图上的任何修改都会直接反映到源数据上,如果需要一份数组的副本,需要显示的使用.copy()方法。
(1)一维数组:
arr = np.arange(10)
arr
输出:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr[5]
输出:5
arr[5:8]
输出:array([5, 6, 7])
arr[5:8] = 12
arr
输出:array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
arr_slice = arr[5:8]
arr_slice[1] = 12345
arr
输出:array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9])
arr_slice[:] = 64
arr
输出:array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
(2)二维数组:
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[2]
输出:array([7, 8, 9])
arr2d[0, 2]
输出:3
arr2d[0][2]
输出:3
arr2d[0, 2]与arr2d[0][2]是一样的。二维数组的元素索引如下图:

arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
old_values = arr3d[0].copy()
arr3d[0] = 42 #标量可以被赋值给切片
arr3d
输出:array([[[42, 42, 42],
[42, 42, 42]],
[[ 7, 8, 9],
[10, 11, 12]]])
arr3d[0] = old_values #数组也可以被赋值给切片
arr3d
输出:array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
以下这张图是几个切片索引的表达方式与对应的切片结果。

代码示例:
arr2d
输出:array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
arr2d[:2]
输出:array([[1, 2, 3],
[4, 5, 6]])
arr2d[:2, 1:]
输出:array([[2, 3],
[5, 6]])
arr2d[1, :2]
输出:array([4, 5])
arr2d[2, :1]
输出:array([7])
arr2d[:, :1]
输出:array([[1],
[4],
[7]])
2、布尔型索引
可以通过一组布尔型数组来对数据型数组进行索引。
from numpy.random import randn
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = randn(7, 4) #按照正态分布生成随机数
names
输出:array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4')
data
输出:array([[-1.12065753, 1.46287992, 0.13695028, -1.89878434],
[ 0.64101753, 0.76381041, 0.04337704, -0.69203921],
[-1.42369882, -0.2431481 , -0.87991876, -0.09632813],
[ 1.11837109, -0.61663551, -0.64223259, -0.9039365 ],
[ 1.5800926 , 0.3459128 , 0.93263276, -1.54058094],
[ 0.64699604, -0.44701417, 0.04640802, -1.28835763],
[ 1.15767592, 0.72404547, 0.38619207, 1.81253003]])
names == 'Bob'
输出:array([ True, False, False, True, False, False, False])
data[names == 'Bob']
输出:array([[-1.12065753, 1.46287992, 0.13695028, -1.89878434],
[ 1.11837109, -0.61663551, -0.64223259, -0.9039365 ]])
data[names == 'Bob', 2:]
输出:array([[ 0.13695028, -1.89878434],
[-0.64223259, -0.9039365 ]])
data[names == 'Bob', 0]
输出:array([-1.12065753, 1.11837109])
data[names != 'Bob'] #与&,或|, 非!=或者在布尔表达式前加-
输出:array([[ 0.64101753, 0.76381041, 0.04337704, -0.69203921],
[-1.42369882, -0.2431481 , -0.87991876, -0.09632813],
[ 1.5800926 , 0.3459128 , 0.93263276, -1.54058094],
[ 0.64699604, -0.44701417, 0.04640802, -1.28835763],
[ 1.15767592, 0.72404547, 0.38619207, 1.81253003]])
mask = (names == 'Bob') | (names == 'Will')
data[mask]
输出:array([[-1.12065753, 1.46287992, 0.13695028, -1.89878434],
[-1.42369882, -0.2431481 , -0.87991876, -0.09632813],
[ 1.11837109, -0.61663551, -0.64223259, -0.9039365 ],
[ 1.5800926 , 0.3459128 , 0.93263276, -1.54058094]])
可以通过布尔型数组设置值:
data[data < 0] = 0
data
输出:array([[0. , 1.46287992, 0.13695028, 0. ],
[0.64101753, 0.76381041, 0.04337704, 0. ],
[0. , 0. , 0. , 0. ],
[1.11837109, 0. , 0. , 0. ],
[1.5800926 , 0.3459128 , 0.93263276, 0. ],
[0.64699604, 0. , 0.04640802, 0. ],
[1.15767592, 0.72404547, 0.38619207, 1.81253003]])
data[names != 'Joe'] = 7
data
输出:array([[7. , 7. , 7. , 7. ],
[0.64101753, 0.76381041, 0.04337704, 0. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[0.64699604, 0. , 0.04640802, 0. ],
[1.15767592, 0.72404547, 0.38619207, 1.81253003]])
3、花式索引
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
arr
输出: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.]])
arr[[4, 3, 0, 6]]
输出:array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
arr[[-1, -3, -5]] #负数索引从后向前计数,从-1开始
输出:array([[7., 7., 7., 7.],
[5., 5., 5., 5.],
[3., 3., 3., 3.]])
arr = np.arange(32).reshape((8, 4))
arr[[1, 5, 7, 2], [0, 3, 1, 2]]
输出:array([ 4, 23, 29, 10])
arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
输出:array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]
#np.ix_函数,可以将两个一维数组转化为一个选取方形区域的索引器
输出:array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])