本专栏第一篇开始讲解NumPy数组,在这么多第三方库中,NumPy是属于比较繁杂但实用的一个库。本篇讲解NumPy基础入门,下一篇讲解numpy API。官方文档的内容比较多,不是非常适用的就不拿出来讲了,偶尔有兴趣可以再去通读官方文档。
官方文档:https://numpy.org/devdocs/user/quickstart.html
先放一下本篇所讲内容的思维导图,看懂教程再看思维导图理解,基本就能掌握NumPy库的一般用法了。
NumPy是用Python进行科学计算的基本库,它提供多维数组对象、各种派生对象(例如蒙版数组和矩阵)和各种数组快速运算的例行程序,包括数学、逻辑、尺寸操作、排序、选择、输入输出、离散傅里叶变换、基本线性代数、基本统计运算和随机模拟等等。
NumPy库的核心是ndarray对象,它封装了同类数据类型的n维数组,很多运算都是在编译过的代码中执行。NumPy和标准Python序列有以下几个重要区别:
Windows系统下安装NumPy
Anaconda软件:
# conda控制台安装
conda install numpy
# Windows控制台安装
pip install numpy
pip3 install numpy
Pycharm软件:
import numpy as np
数组常用属性 | 说明 |
---|---|
ndarray.ndim |
数组维度 integer。 |
ndarray.shape |
数组尺寸 (row,col)。 |
ndarray.size |
数组元素个数。 |
ndarray.dtype |
数组元素的数据类型。 |
ndarray.itemsize |
数组每个元素所占内存大小(以字节为单位)。 |
import numpy as np
a = np.arange(15).reshape(3,5) # 创建包含0~14的一维数组,并把尺寸更改为3×5
print(a)
"""
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
"""
print(a.shape) # (3, 5)
print(a.ndim) # 2
print(a.size) # 15
print(a.dtype) # int32
print(a.itemsize) # 4
print(a.data) #
print(type(a)) #
有几种创建数组的方法。例如,你可以使用array()函数从常规的Python列表或元组创建一个数组,可通过列表或元组中元素的数据类型来推断所得数组的元素数据类型。
import numpy as np
a = np.array([2,3,4])
print(a,a.dtype) # [2 3 4] int32
b = np.array([1.2,3.5,5.1])
print(b,b.dtype) # [1.2 3.5 5.1] float64
import numpy as np
a = np.array([(1.5,2,3), (4,5,6)])
print(a)
"""
[[1.5 2. 3. ]
[4. 5. 6. ]]
"""
import numpy as np
c = np.array( [ [1,2], [3,4] ], dtype=complex )
print(c)
"""
[[1.+0.j 2.+0.j]
[3.+0.j 4.+0.j]]
"""
方法 | 说明 |
---|---|
np.zeros () |
创建全0数组。 |
np.ones () |
创建全1数组。 |
np.empty () |
创建空数组,数组的元素是随机的。 |
import numpy as np
a1 = np.zeros(3) # 创建一维数组
print(a1,a1.dtype) # [0. 0. 0.] float64
a2 = np.zeros((3,4),dtype="int32") # 创建二维数组,数据类型指定为int32
print(a2)
"""
[[0 0 0 0]
[0 0 0 0]
[0 0 0 0]]
"""
b = np.ones((2,3,4)) # 创建三维数组
print(b)
"""
[[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]
[[1. 1. 1. 1.]
[1. 1. 1. 1.]
[1. 1. 1. 1.]]]
"""
c = np.empty((2,3))
print(c)
"""
[[6.23042070e-307 3.56043053e-307 1.37961641e-306]
[6.23039354e-307 1.69115935e-306 0.00000000e+000]]
"""
import numpy as np
a = np.linspace(0,2,9) # 在[0,2]线性产生含有9个元素的数组
print(a)
# [0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. ]
打印方式 | 说明 |
---|---|
print() | 直接打印,当数据量非常大时会隐藏中间数据。 |
np.set_printoptions (threshold=sys.maxsize) |
全部打印,通过这行代码声明打印时显示所有数据。 |
import numpy as np
print(np.arange(10000))
# [ 0 1 2 ... 9997 9998 9999]
import sys
import numpy as np
np.set_printoptions(threshold=sys.maxsize)
print(np.arange(10000))
数组运算 | 说明 |
---|---|
+ 、- 、* |
数组相加、相减、相乘。 |
+= 、-= 、*= |
数组相加、相减、相乘。 |
@ 或dot () |
矩阵相乘(@适用于Python3.5以后的版本)。 |
numpy.max () |
求数组元素最大值(可通过指定axis=0(按列)、axis=1(按行)求行或列的最大值)。 |
numpy.min () |
求数组元素最小值(可通过指定axis=0(按列)、axis=1(按行)求行或列的最小值)。 |
numpy.sum () |
数组求和(可通过指定axis=0(按行)、axis=1(按列)求行或列的和)。 |
numpy.cumsum () |
数组求累加和(可通过指定axis=0(按行)、axis=1(按列)求行或列的累加和)。 |
import numpy as np
a = np.array( [20,30,40,50] )
b = np.arange(4)
c = a - b
d = b**2
print(a,b,sep="\n")
"""
[20 30 40 50]
[0 1 2 3]
"""
print(c) # [20 29 38 47]
print(d) # [20 29 38 47]
A = np.array( [[1,1],[0,1]] )
B = np.array( [[2,0],[3,4]] )
C1 = A * B # elementwise product
C2 = A @ B # matrix product (Python>=3.5)
C3 = A.dot(B) # matrix product
print(C1,C2,C3,sep="\n\n")
"""
[[2 0]
[0 4]]
[[5 4]
[3 4]]
[[5 4]
[3 4]]
"""
A *= 3
B += A
print(A)
"""
[[3 3]
[0 3]]
"""
print(B)
"""
[[5 3]
[3 7]]
"""
C = np.random.random((2,3))
print(C)
"""
[[0.72455309 0.57577621 0.6516948 ]
[0.56008549 0.97001158 0.17850673]]
"""
print(C.sum()) # 3.66062790490271
print(C.min()) # 0.17850673463686328
print(C.max()) # 0.970011580490359
print(C.min(axis=0)) # [0.56008549 0.57577621 0.17850673]
D = np.arange(12).reshape(3,4)
print(D)
"""
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
"""
print(D.sum(axis=0))
# [12 15 18 21]
print(D.sum(axis=1))
# [ 6 22 38]
print(D.cumsum())
# [ 0 1 3 6 10 15 21 28 36 45 55 66]
print(D.cumsum(axis=1))
"""
[[ 0 1 3 6]
[ 4 9 15 22]
[ 8 17 27 38]]
"""
NumPy提供熟悉的数学函数,例如sin,cos和exp。在NumPy中,这些函数称为通用函数(ufunc),它们在数组上逐元素运算,生成一个数组作为输出。
import numpy as np
a = np.sin([np.pi/6,np.pi/2,np.pi])
print(a) # [5.0000000e-01 1.0000000e+00 1.2246468e-16]
b1 = np.exp(np.arange(3))
b2 = np.exp([0,1,2])
print(b1) # [1. 2.71828183 7.3890561 ]
print(b2) # [1. 2.71828183 7.3890561 ]
c = np.sqrt(b2)
print(c) # [1. 1.64872127 2.71828183]
d = np.add(b2,c)
print(d) # [ 2. 4.3670031 10.10733793]
NumPy的一维数组非常像Python中的列表和其他序列,可以被索引、切片和遍历。下面以Python一维列表的索引和切片方式来对NumPy一维数组进行索引和切片。
import numpy as np
a = np.arange(10)**3
print(a) # [ 0 1 8 27 64 125 216 343 512 729]
print(a[2]) # 8
print(a[-1]) # 729
print(a[1:4]) # [ 1 8 27]
print(a[2::]) # [ 8 27 64 125 216 343 512 729]
print(a[0:-1]) # [ 0 1 8 27 64 125 216 343 512]
print(a[::-1]) # [729 512 343 216 125 64 27 8 1 0]
NumPy二维数组的索引和切片方式和MATLAB二维数组的索引和切片方式基本一致。
索引或切片方式 | 说明 |
---|---|
a[m,n] | 取数组a第m行第n列的元素。 |
a[i:j,k] | 取数组a第i~第j-1行,第k列的元素。 |
a[k,i:j] | 取数组a第i~第j-1列,第k行的元素。 |
a[i,:] | 取数组a第i行所有列的元素。 |
a[:,j] | 取数组a第j列所有行的元素。 |
a[i:j,k:q] | 取数组a第i到第j-1行,第k到第q-1列的所有元素。 |
import numpy as np
def f(x,y):
return 10*x + y
a = np.fromfunction(f, (5,4),dtype=int)
print(a)
"""
[[ 0 1 2 3]
[10 11 12 13]
[20 21 22 23]
[30 31 32 33]
[40 41 42 43]]
"""
print(a[2,3]) # 23
print(a[0:5,1]) # [ 1 11 21 31 41]
print(a[:,1]) # [ 1 11 21 31 41]
print(a[1:3,:])
"""
[[10 11 12 13]
[20 21 22 23]]
"""
import numpy as np
# 一维数组遍历
array = np.arange(5)
print(array) # [0 1 2 3 4]
for a in array:
print(a)
"""
0
1
2
3
4
"""
# 二维数组遍历
b = np.arange(10,16).reshape(2,3)
print(b)
"""
[[10 11 12]
[13 14 15]]
"""
for row in b: # 按列表遍历方式遍历
print(row) # b本质是一个ndarray类的对象,所以会直接输出数组本身
"""
[10 11 12]
[13 14 15]
"""
for element in b.flat: # 先将数组扁平化为一维数组后再遍历
print(element)
"""
10
11
12
13
14
15
"""
方法 | 说明 |
---|---|
ndarray.reshape () |
改变数组的形状,返回副本。原数组的尺寸没有改变。 |
ndarray.resize () |
直接改变原数组的尺寸。 |
import numpy as np
arr1 = np.array([0,1,2,3,4,5])
arr1.reshape(2,3)
print(arr1) # [0 1 2 3 4 5]
arr2 = arr1.reshape(2,3)
print(arr2)
"""
[[0 1 2]
[3 4 5]]
"""
arr1.resize(2,3)
print(arr1)
"""
[[0 1 2]
[3 4 5]]
"""
组合方式 | 说明 |
---|---|
np.vstack ((a,b)) |
按纵向组合。 |
np.hstack ((a,b)) |
按横向组合。 |
import numpy as np
a = np.array([[9,7],[5,2]])
b = np.array([[1,9],[5,1]])
print(a)
"""
[[9 7]
[5 2]]
"""
print(b)
"""
[[1 9]
[5 1]]
"""
print(np.vstack((a,b)))
"""
[[9 7]
[5 2]
[1 9]
[5 1]]
"""
print(np.hstack((a,b)))
"""
[[9 7 1 9]
[5 2 5 1]]
"""
拆分方式 | 说明 |
---|---|
np.vsplit (a,k) |
纵向拆分。k为整数时,表示拆分为k个数组(要求k能被数组的行数整数);k为元组(m,m+1)时,表示以m列为间隔拆分。 |
np.hsplit (a,k) |
横向拆分。k取值同理。 |
import numpy as np
a = np.arange(24).reshape(2,12)
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]]
"""
print((np.hsplit(a,3)))
"""
[array([[ 0, 1, 2, 3],
[12, 13, 14, 15]]), array([[ 4, 5, 6, 7],
[16, 17, 18, 19]]), array([[ 8, 9, 10, 11],
[20, 21, 22, 23]])]
"""
print(np.hsplit(a,(3,4)))
"""
[array([[ 0, 1, 2],
[12, 13, 14]]), array([[ 3],
[15]]), array([[ 4, 5, 6, 7, 8, 9, 10, 11],
[16, 17, 18, 19, 20, 21, 22, 23]])]
"""
拷贝方式 | 说明 |
---|---|
= |
无拷贝(相当于给对象的引用起了一个别名)。 |
view () |
浅拷贝(产生新对象,与原对象共享内存)。 |
copy () |
深拷贝(产生新对象和新内存)。 |
import numpy as np
a = np.arange(12)
b = a
print(id(a)) # 2264262477664
print(id(b)) # 2264262477664 没有产生新对象
b.resize(2,6) # a和b本质为同一个对象,b改变,a也随着改变
print(a)
"""
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
"""
import numpy as np
a = np.arange(12).reshape(3,4)
b = a.view()
print(id(a)) # 2264262871600
print(id(b)) # 2264262872880 产生新对象
b[0,2] = 1234 # 直接修改内存中数组的数据,所以a也改变
print(a)
"""
[[ 0 1 1234 3]
[ 4 5 6 7]
[ 8 9 10 11]]
"""
import numpy as np
a = np.arange(12).reshape(3,4)
b = a.copy()
print(id(a)) # 2264262500144
print(id(b)) # 2264242768192 产生新对象
b[0,2] = 1234
print(a) # 数组a没有改变
"""
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
"""
print(b) # 产生新内存,修改数组b的数据不影响数组a
"""
[[ 0 1 1234 3]
[ 4 5 6 7]
[ 8 9 10 11]]
"""
import numpy as np
a = np.arange(12).reshape(3,4)
b1 = np.array([False,True,True])
b2 = np.array([True,False,True,False])
print(a)
"""
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
"""
print(a[b1,:]) # 取数组a第1行和第2行的所有列的数据
"""
[[ 4 5 6 7]
[ 8 9 10 11]]
"""
print(a[b1,b2]) # 取数组a第1行~第2行,第0列和第2列的数据
"""
[ 4 10]
"""
import numpy as np
a = np.array([[1.0, 2.0], [3.0, 4.0]])
a.transpose() # 将数组a转置
print(a)
"""
[[1. 2.]
[3. 4.]]
"""
b = np.linalg.inv(a) # 对转置后的数组a求逆
print(b)
"""
[[-2. 1. ]
[ 1.5 -0.5]]
"""
c = np.array([[2,1],[-1,1]])
print(c @ c) # 矩阵相乘
"""
[[ 3 3]
[-3 0]]
"""
x = np.array([[1.0, 2.0], [3.0, 4.0]])
y = np.array([[5],[7]])
print(np.linalg.solve(x,y)) # 解线性方程
"""
[[-3.]
[ 4.]]
"""
print(np.linalg.eig(x)) # 求特征值和特征向量
"""
(array([-0.37228132, 5.37228132]), array([[-0.82456484, -0.41597356],
[ 0.56576746, -0.90937671]]))
"""