目录
一、复习numpy.arange和Numpy数组属性
numpy.arangenumpy.arange(start, stop, step, dtype)
根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray。
numpy.linspace创建等差数列np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
numpy.logspace创建等比数列np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
Numpy数组基本属性:
二、学习新知识
1.切片和索引
ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。
ndarray 数组可以基于 0 - n 的下标进行索引。
1.1 普通索引
使用冒号分隔切片参数 start:stop:step 来进行切片操作:
一维数组的索引:
首先创建一个ndarray对象:
ar1 = np.arange(10)
ar1
输出:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
从索引 2 开始到索引 7 停止,间隔为 2:
ar2 = ar1[2:7:2]
ar2
输出:
array([2, 4, 6])
对冒号:的解释:如果之放置一个参数,
如[2],将返回与该索引相对应的单个元素
如[2:],表示从该索引开始以后的所有项都将被提取
如果使用了两个参数,如[2:7],那么则提取两个索引(不包括停止索引)之间的项
如:
ar3 = np.arange(1,20,2)
ar3
输出:
array([ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19])
取索引为4的元素ar3[4]
输出:
9
取最后一个元素ar3[-1]
输出:
19
取所有数据,步长-1:ar3[::-1]
输出:
array([19, 17, 15, 13, 11, 9, 7, 5, 3, 1])
取数据1到17之间,并且间隔一位的数据:ar3[:-2:2]
输出:
array([ 1, 5, 9, 13])
不包括开头的数据1:ar3[1:-2:2]
输出:
array([ 3, 7, 11, 15])
二维数组的索引:
定义4行5列的数据:
ar4_5 = np.arange(20).reshape(4,5)
ar4_5
输出:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
取索引为2的元素ar4_5[2]
输出:
array([10, 11, 12, 13, 14]) #取出第二行的数据
取出索引为[2][2]的数据:ar4_5[2][2]
输出:
12
取索引为2之后的数据:ar4_5[2:]
输出:
array([[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
注意:切片还可以使用省略号"…",如果在行位置使用省略号,那么返回值将包含所有行元素,反之,将包含所有列元素
如:得第二列数据ar4_5[...,1]
输出:
array([ 1, 6, 11, 16])
返回第二列后的所有项:ar4_5[...,1:]
输出:
array([[ 1, 2, 3, 4],
[ 6, 7, 8, 9],
[11, 12, 13, 14],
[16, 17, 18, 19]])
返回2行3列数据ar4_5[1,2] == ar4_5[1][2]
输出:
True
返回第二列的所有项:ar4_5[...][1] == ar4_5[1] ##([5,6,7,8,9])
输出:
array([ True, True, True, True, True])
1.2 高级索引
除了之前看到的用整数和切片的索引外,数组可以由整数数组索引、布尔索引及花式索引。
1.2.1 整数数组索引
以下实例获取数组中(0,0),(1,1)和(2,0)位置处的元素。
x = np.array([
[1, 2],
[3, 4],
[5, 6]
])
#[0,1,2]代表行索引,[0,1,0]代表列索引
y = x[[0,1,2],[0,1,0]]
#y分别获取x中的(0,0),(1,1),(2,0)的数据
y
输出:
array([1, 4, 5])
取数组(0,0),(2,2),(3,0),(3,2)处的元素:
b = np.array([
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10, 11]
])
r = np.array([[0,2],[3,3]]).reshape(4)
l = np.array([[0,2],[0,2]]).reshape(4)
s = b[r,l].reshape((2,2))
s
输出:
array([[ 0, 8],
[ 9, 11]])
行取得2行和3行,列取得2列和3列的3种方式:
a = np.array([
[1,2,3],
[4,5,6],
[7,8,9]
])
#行取得2行和3行,列取得2列和3列
b = a[1:3, 1:3]
c = a[1:3,[1,2]]#1:3== [1,2]
d = a[..., 1:]
print(b)
print(c)
print(d)
输出:
[[5 6]
[8 9]]
[[5 6]
[8 9]]
[[2 3]
[5 6]
[8 9]]
例子:创建一个8*8的国际象棋棋盘矩阵(黑块为0,白块为1)
对于一个全0数组:
Z = np.zeros((8,8),dtype = int)
先按行观察 交叉位置为1:
设置
Z[1::2, ::2] = 1
得到:
再按列走一遍交叉位置。
最终代码:
Z = np.zeros((8,8),dtype = int)
Z[1::2, ::2] = 1
Z[::2,1::2] = 1
Z
输出:
array([[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0]])
1.2.2 布尔数组索引
当输出的结果需要布尔运算(如比较运算)时,会用到另一种高级索引方式,即布尔数组索引。下面示例返回大于6的所有元素
x = np.array([[0,1,2],[3,4,5],[6,7,8],[9,10,11]])
x[x>6]
输出:
array([ 7, 8, 9, 10, 11])
例子:提取出数组中所有奇数 并将奇数值修改为1
x[x%2 == 1] = 1
x
输出:
array([[ 0, 1, 2],
[ 1, 4, 1],
[ 6, 1, 8],
[ 1, 10, 1]])
筛选出指定区间内数据:&和 |或
如:取x中大于4并且小于9的数据
x = np.array([[0, 1, 2],[3, 4, 5],[6, 7, 8],[9, 10, 11]])
#x中大于4并且小于9的数据
x[(x>4)&(x<9)]
输出:
array([5, 6, 7, 8])
数组索引及切片的值更改会修改原数组:
ar = np.arange(10)
print(ar)
ar[5] = 100
ar[7:9] = 200
print(ar)
#一个标量赋值给一个索引/切片时,会自动改变/传播原始数组
输出:
[0 1 2 3 4 5 6 7 8 9]
[ 0 1 2 3 4 100 6 200 200 9]
若不想改变原始数组,可以从copy()一份副本进行修改
#复制操作
ar = np.arange(10)
b = ar.copy()
#或者 b=np.array(ar)
b[7:9] = 200
print('ar:',ar)
print('b:', b)
输出:
ar: [0 1 2 3 4 5 6 7 8 9]
b: [ 0 1 2 3 4 5 6 200 200 9]
1.2.3 花式索引
花式索引指的是利用整数数组进行索引。
花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应下标的行,如果目标是二维数组,那么就是对应位置的元素。
花式索引跟切片不一样,它总是将数据复制到新数组中。
如:
新建一个数组
x=np.arange(32).reshape((8,4))
print(x)
输出:
[[ 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]
[28 29 30 31]]
print (x[[4,2,1,7]])
输出:
[[16 17 18 19]
[ 8 9 10 11]
[ 4 5 6 7]
[28 29 30 31]]
传入倒序索引数组:print (x[[-4,-2,-1,-7]])
输出:
[[16 17 18 19]
[24 25 26 27]
[28 29 30 31]
[ 4 5 6 7]]
2.广播机制
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。
如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。
例1:
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])
c = a * b
print(c)
输出:
[ 10 40 90 160]
例2:
当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。如:
a = np.array([
[0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]
])
b = np.array([1,2,3])
print(a + b)
输出:
[[ 1 2 3]
[11 12 13]
[21 22 23]
[31 32 33]]
广播的规则:
让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
输出数组的形状是输入数组形状的各个维度上的最大值。
如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
广播这里可以参考知乎一篇文章NumPy中的广播机制