NumPy是一个专门用来进行数学计算的第三方库,对线性代数的支持较好。(Matlab与Python一较高下?期待...)
2.1 NumPy库安装和基本方法
安装好pip后,在cmd窗口输入:pip install numpy口令就好了。
Python没有数组类型,只能用列表这种类似数组的类型替代,但这一缺陷就可以有NumPy库来弥补。由NumPy官方手册介绍,NumPy库的主要对象是由同种类型数据构成的“多维数组”(理解成n维数组)。
在NumPy库里,axes 代表维度,length代表数组长度。支持多维度的数组对象被称为“ndarray”,通过numpy.ndarray来调用。不同于Python的工厂函数array.array,ndarray提供的方法更多且更实用。如下表提供的一些简单的方法
基本方法 | 描述 |
ndarray.ndim | 返回一个int值,用来表示数组的维度 |
ndarray.size | 返回一个数组的总元素个数 |
ndarray.dtype | 一个描述数组里包含的数字所属类型的对象,可以是Python自带的数据类型也可以是NumPy库附加的数据类型 |
ndarray.shape | 显示这个数组的维度,返回一个元组。例:r行c列就返回(r,c) |
ndarray.itemsize | 显示每个元素的比特位。例:float61是8(64/8)比特,complex32(32/8)是4比特,int16是4比特 |
ndarray.data | 一个包含实际元素的数组的缓冲区,查找元素操作可以使用索引序号,一般不会用到 |
2.2 创建一个数组
用列表或元组来创建一个二维数组
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([(1, 2, 3), (4, 5, 6)])
c = np.arange(1, 7).reshape(2, 3) # 利用迭代创建,arange和Python中range类似,reshape(行,列)
print(a)
print(b)
print(a == b)
print(c)
"""
结果好神奇:
[[1 2 3]
[4 5 6]]
[[1 2 3]
[4 5 6]]
[[ True True True]
[ True True True]]
[[1 2 3]
[4 5 6]]
"""
2.2.1 reshape()
reshape()方法它可以重塑数组,格式为:
numpy.reshape(a, newshape, order=’C’)
a:array_like
要重新形成的数组。
newshape:int或tuple的整数
新的形状应该与原始形状兼容。如果是整数,则结果将是该长度的1-D数组。一个形状维度可以是-1。在这种情况下,从数组的长度和其余维度推断该值。
order(可选参数):{'C','F','A'}可选
使用此索引顺序读取a的元素,并使用此索引顺序将元素放置到重新形成的数组中。
C代表与C语言类似,行优先;
F代表列优先
注意,'C'和'F'选项不考虑底层数组的内存布局,而只是参考索引(行优先还是列优先而已)的顺序。
'A'意味着在Fortran类索引顺序中读/写元素,如果a 是Fortran 在内存中连续的,否则为C样顺序。
关于reshape参数中-1的作用:数组新的shape属性应该要与原来的配套,如果等于-1的话,那么Numpy会根据剩下的维度计算出数组的另外一个newshape属性值。
# 例子:把2行4列数组转换为4行2列
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
a = a.reshape(3, 2)
print(a)
"""
amazing!结果为:
[[1 2]
[3 4]
[5 6]]
"""
#关于参数为-1
d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
d = d.reshape(-1, 2)
print(d)
"""
结果为:
[[ 1 2]
[ 3 4]
[ 5 6]
[ 7 8]
[ 9 10]
[11 12]
[13 14]
[15 16]]
也就是说,我固定行(列),剩下的我不想算列(行)的个数,直接用-1,它会自动计算出多少列(行)
"""
2.2.2 arange()
arange()方法只是类似于range()方法迭代整型变量的情况,如果要迭代浮点数,需要使用linspace()方法
import numpy as np
a1 = np.arange(0, 53, 3).reshape(3, -1) # 从0到53间隔3个迭代取数
print("a1:", a1)
b1 = np.linspace(0, 53, 3).reshape(3, -1) # 从0到53,化为3段
print("b1:", b1)
c1 = np.linspace(0, 53, 18).reshape(3, -1) # 只有linspace(0, 53, 18)这样写才能得到想要的数据
print("c1:", c1)
"""
结果为:
a1: [[ 0 3 6 9 12 15]
[18 21 24 27 30 33]
[36 39 42 45 48 51]]
b1: [[ 0. ]
[26.5]
[53. ]]
c1: [[ 0. 3.11764706 6.23529412 9.35294118 12.47058824 15.58823529]
[18.70588235 21.82352941 24.94117647 28.05882353 31.17647059 34.29411765]
[37.41176471 40.52941176 43.64705882 46.76470588 49.88235294 53. ]]
"""
2.2.3 dtype
在生成矩阵时也可以使用dtype参数指定数据类型,dtype默认时整型,还可设置整型、浮点型和复数型等:
import numpy as np
a2 = np.array([[1, 2, 3], [4, 5, 6]]) # 默认整型
b2 = np.array([[1, 2, 3], [4, 5, 6]], dtype=float) # 浮点型
c2 = np.array([[1, 2, 3], [4, 5, 6]], dtype=complex) # 复数型
print(a2)
print(b2)
print(c2)
"""
结果为:
[[1 2 3]
[4 5 6]]
[[1. 2. 3.]
[4. 5. 6.]]
[[1.+0.j 2.+0.j 3.+0.j]
[4.+0.j 5.+0.j 6.+0.j]]
"""
2.2.4 zeros()
zeros()方法生成“零矩阵”
"""
格式:np.zeros(shape, dtype=float, order=‘C’)
shape:1.传入一个数字,它将生成一个一维的向量;2.传入一个元组,它将生成以元组中各数字作为维度值的矩阵,比如zeros((2,4))->>>就是2行4列的零矩阵
dtype:在2.2.3节讲了,默认为float
order:可选参数,c代表与c语言类似,行优先;F代表列优先。
"""
import numpy as np
print(np.zeros(5)) # 一维
print(np.zeros((4, 4))) # 4 x 4的矩阵
"""
结果为:
[0. 0. 0. 0. 0.]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
"""
2.2.5 ones()
用ones()方法生成“全1矩阵”
"""
np.ones(shape, dtype=float, order='C')
# shape:返回的数组的维度或形状(和zeros的shape属性类似)
# dtype:可选参数,返回的数组内数据的数据类型,默认是float
# order:可选参数,与C语言类似,C代表行优先,F代表列优先
"""
import numpy as np
print(np.ones(5)) # 一维
print(np.ones((4, 4))) # 4 x 4的矩阵
"""
[1. 1. 1. 1. 1.]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
"""
2.2.6 empty()
用empty()方法生成“随机浮点数矩阵”
"""
np.ones(shape, dtype=float, order='C')
# shape:返回的数组的维度或形状(和zeros的shape属性类似)
# dtype:可选参数,返回的数组内数据的数据类型
# order:可选参数,与C语言类似,C代表行优先,F代表列优先
"""
import numpy as np
print(np.empty(6)) # 一维
print(np.empty((4, 5))) # 4 x 5的矩阵
"""
[0. 0. 0. 0. 0. 0.]
[[6.23042070e-307 1.42417221e-306 1.37962660e-306 6.23059726e-307
1.95821439e-306]
[8.01097889e-307 1.78020169e-306 7.56601165e-307 1.02359984e-306
1.33510679e-306]
[2.22522597e-306 1.33511018e-306 6.23057689e-307 1.02360120e-306
8.45559303e-307]
[8.06613465e-308 6.89810244e-307 1.22387550e-307 2.22522596e-306
1.33511969e-306]]
"""
2.2.7 快速生成指数e大小
"""
格式为:
np.exp(n),n为指数,也就是e^n
"""
import numpy as np
print(np.exp(1)) # 2.718281828459045
2.2.8 快速生成圆周率大小
import numpy as np
print(np.pi) # 3.141592653589793
当显示较长的矩阵时,会用省略号省去
import numpy as np
print(np.arange(10000).reshape(100, 100))
"""
[[ 0 1 2 ... 97 98 99]
[ 100 101 102 ... 197 198 199]
[ 200 201 202 ... 297 298 299]
...
[9700 9701 9702 ... 9797 9798 9799]
[9800 9801 9802 ... 9897 9898 9899]
[9900 9901 9902 ... 9997 9998 9999]]
"""
2.3 索引、切片和迭代
一维数组也是一维矩阵,同样也是一个列表,所以n维矩阵(n维数组)依然支持索引、切片和迭代操作。
2.3.1 索引和切片
一维示例(规则和列表的索引类似):
import numpy as np
# 打印数组
a = np.arange(100) # 创建一个一维数组
print(a)
"""
[ 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
96 97 98 99]
"""
# 进行索引
print("索引操作:")
print(a[3]) # 找下标为3的元素
# 结果为:3
print("打印下标前10的元素:", end=' ') # 用的是下标,而不是迭代器
for i in range(10):
print(a[i], end=' ')
print()
# 结果为:0 1 2 3 4 5 6 7 8 9
# 切片操作
print("正序号10到20:", a[10:21]) # 结果为[10 11 12 13 14 15 16 17 18 19 20]
print("间隔为5,切片用逆序:", a[-10:-1:5]) # 结果为:[90 95]
a[:3] = 1
print("用切片操作先修改再打印:", a[:5]) # 结果为:[1 1 1 3 4]
# 迭代操作
print("迭代操作")
# 利用迭代器
for i in a:
print(i) # 输出到99
多维矩阵中的每个维度都有独立的一组序号,所以二维矩阵可以用两个数进行索引;n维矩阵可以用n个数进行索引。
在举二维数组例子之前,学习一下fromfunction():生成矩阵用的函数,代码格式为:
numpy.fromfunction(function, shape, *, dtype=<class 'float'>, **kwargs)
参数作用:
- function :callable该函数使用N个参数调用,其中N是的秩 shape。每个参数代表沿特定轴变化的数组坐标。例如,如果shape 为(2, 2),则参数将为(2, 2)array([[0, 0], [1, 1]]) 和 array([[0, 1], [0, 1]])
- shape :(N,)个整数元组输出数组形式,它也确定传递给function的坐标数组的形状。
- dtype:可选传递给function的坐标数组的数据类型。默认情况下dtype为float。
import numpy as np
def f1(x,y):
return x
def f2(x,y):
return y
def f3(x,y):
return 2*x+y
a = np.fromfunction(f1, (5, 1), dtype=int)
print(a)
"""
结果为:
[[0]
[1]
[2]
[3]
[4]],可以发现:shape定义了输出矩阵的大小,在这个例子,体现了x为5行1列的矩阵(列向量)
"""
a1 = np.fromfunction(f1, (5, 5), dtype=int)
print(a1)
"""
结果为:
[[0 0 0 0 0]
[1 1 1 1 1]
[2 2 2 2 2]
[3 3 3 3 3]
[4 4 4 4 4]]
在这个例子中,shape(5,5),第一个5表示为5行,第二个5表示为5列,
而调用的f1函数,则是为了体现x为5行1列的矩阵(列向量)
"""
b = np.fromfunction(f2, (1, 5), dtype=int)
print(b)
# 结果为:[[0 1 2 3 4]],由此可以看出,函数中y表示为1行5列的矩阵(行向量)
b1 = np.fromfunction(f2, (5, 5), dtype=int)
print(b1)
"""
结果为:
[[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]
[0 1 2 3 4]]
"""
c = np.fromfunction(f3, (5, 5), dtype=int)
print(c)
"""
结果为:
[[ 0 1 2 3 4]
[ 2 3 4 5 6]
[ 4 5 6 7 8]
[ 6 7 8 9 10]
[ 8 9 10 11 12]]
在这个例子中,函数中2*x表示控制元素的间隔为2,同理2*y也是控制元素的间隔为2
所以n*x(y)表示间隔为n
"""
从这篇numpy函数fromfunction分析 - 啊哈彭 - 博客园文章学到的知识。
多维示例:在这里需要注意几个点:
- 多维数组索引时:中括号[]中,行列用逗号(,)分开,比如二维矩阵b,我想找第三行第四列的元素,那就是b[3, 4]。(就类似数组的b[3][4])
- 多维数组的切片时:1.第一维索引:中括号[]中,第一个冒号(:)前为索引的起始值,第一个冒号(:)后为索引的结束值(还是遵循取左不取右规则);2.第二维索引:接着逗号(,)后面时数组的第二维索引,数组各维的索引方式和第一维索引方式相同。比如b[1:4:2, ::2]:1:4:2表示第一维的第1行(从0行开始),第3行(不取第4行),间隔为2;::2:表示对前面的起始和结束索引位置不做限制,间隔为2,是在第1维的基础上,取第0列和第2列;3.第三维索引:如果后面还有逗号,就是代表第三维,是在第二维得到的矩阵上进行操作,后续就是类似上述操作。4.≥3维的数组,可以通过'...'来简化操作,比如三维数组c,c[1, ...] 就等价于c[1, :, :],c[..., 1]等价于c[:, :, 1]。
import numpy as np
# 生成矩阵用的函数
def func_1(x, y):
return 5 * x + y
# 生成并打印矩阵
b = np.fromfunction(func_1, (5, 4), dtype=int)
print(b)
# 多维数组索引
print("多维数组索引:")
print(b[3, 3]) # 可以理解为数组的b[3][3]
# 多维数组切片
print("多维数组切片:")
# 打印第0列
print(b[:, 0])
# 打印第0行
print(b[0, :])
# 逆序号,打印最后一行,以下两行作用相同
print(b[-1])
print(b[-1, :])
print(b[1: 4: 2])
print(b[1: 4: 2, ::2])
"""
结果为:
[[ 0 1 2 3]
[ 5 6 7 8]
[10 11 12 13]
[15 16 17 18]
[20 21 22 23]]
多维数组索引:
18
多维数组切片:
[ 0 5 10 15 20]
[0 1 2 3]
[20 21 22 23]
[20 21 22 23]
[[ 5 6 7 8]
[15 16 17 18]]
[[ 5 7]
[15 17]]
"""
# 生成一个三位数组
print("打印一个三维数组:")
c = np.arange(1, 19).reshape(2, 3, 3) # 我理解三维数组是以长(x=2)宽(y=3)高(z=3)来理解的...(但是又隐约觉得不对,数学不好唉)
print(c)
print("示例一:")
print(c[1, :, :])
print(c[1, ...])
print("示例二")
print(c[..., 2])
print(c[:, :, 2])
"""
打印一个三维数组:
[[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]]
[[10 11 12]
[13 14 15]
[16 17 18]]]
示例一:
[[10 11 12]
[13 14 15]
[16 17 18]]
[[10 11 12]
[13 14 15]
[16 17 18]]
示例二
[[ 3 6 9]
[12 15 18]]
[[ 3 6 9]
[12 15 18]]
"""
还有一些关于索引和切片的知识(比如布尔型切片等):
这篇文章有写->>>Numpy多维数组索引与切片详解 - 知乎
2.3.2 迭代
在学习迭代之前先学一下关于axis的理解:NumPy中axis的理解_zhwangye的博客-CSDN博客_numpy中的axis
可以学习到:axis为"[ ]"的层数,最外层为axis=0,往里一层便+1。
import numpy as np
print("打印一个三维数组:")
c = np.arange(1, 19).reshape(2, 3, 3)
print(c)
# 迭代一个维度(最外层)
print("迭代一个维度")
for firstAxis in c:
print(firstAxis)
print("迭代两个维度")
for firstAxis in c:
for secondAxis in firstAxis:
print(secondAxis)
print("迭代三个维度方法一")
for firstAxis in c:
for secondAxis in firstAxis:
for thirdAxis in secondAxis:
print(thirdAxis)
# 迭代三个维度还可以用flat方法
print("迭代三个维度方法二")
for element in c.flat:
print(element)
# flat方法是将一个n位数字展开成一维后,再将结果打印出来,二默认遍历的是第一个维度(最外层的维度)
2.4 拼合、划分一个矩阵
全部写在一篇有点多分开写->>>传送门
2.5 深拷贝、浅拷贝与不拷贝
同上->>>传送门
从Pyzhebzthon数据分析从小白到专家_百度百科这本书上学到的知识!