安装
numpy快速入门
数组是 NumPy 库的核心数据结构。创建数组的最简单方法之一是使用array
函数。
1 创建数组
1 2 3 4 5 6 7 8 9
| import numpy as np x = np.array([[1,2,3],[2,3,4]]) print(x) """ 输出: [[1 2 3] [2 3 4]] """
|
array
函数可以在列表甚至嵌套列表上调用。 由于此处输入的嵌套级别是2,因此生成的数组是二维的。 这意味着可以使用两个整数集对数组进行索引。 计算数组维数的最简单方法是检查数组的ndim
属性,也可以通过检查数组的shape
属性,数组中的元素总数使用size
查看:
1 2 3 4 5 6 7 8 9
| print(array.ndim) print(array.shape) print(array.size) """ 输出: 2 (2, 3) 6 """
|
创建初始值为0、为1、空值(随机值)的数组:
1 2 3 4 5 6 7 8 9 10 11 12
| array=np.zeros(2) print(array) array=np.ones(2) print(array) array=np.empty(2) print(array) """ 输出: [0. 0.] [1. 1.] [1. 1.] """
|
使用arange创建数组,它类似于内置range函数:
1 2 3 4 5 6 7 8 9
| array=np.arange(4) print(array) array=np.arange(2, 9, 2) print(array) """ 输出: [0 1 2 3] [2 4 6 8] """
|
创建等间距的数组:
1 2 3 4 5 6
| array=np.linspace(0, 10, num=5) print(array) """ 输出: [ 0. 2.5 5. 7.5 10. ] """
|
以上方法创建的数组默认数据类型为np.float64
,可以在创建时显式地制定它的类型:
1 2 3 4 5 6
| array=np.ones(2, dtype=np.int64) print(array) """ 输出: [1 1] """
|
2 添加、删除和排序元素
初始数组如下:
1
| arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
|
使用sort
对其进行排序:
1 2 3 4 5 6 7 8 9
| arr = np.array([2, 1, 5, 3, 7, 4, 6, 8]) print(arr) arr=np.sort(arr) print(arr) """ 输出: [2 1 5 3 7 4 6 8] [1 2 3 4 5 6 7 8] """
|
对数组进行拼接,使用concatenate
:
1 2 3 4 5 6 7 8
| a = np.array([1, 2, 3, 4]) b = np.array([5, 6, 7, 8]) c=np.concatenate((a,b)) print(c) """ 输出: [1 2 3 4 5 6 7 8] """
|
拼接两个二维数组:
1 2 3 4 5 6 7 8 9 10
| x = np.array([[1, 2], [3, 4]]) y = np.array([[5, 6]]) c=np.concatenate((x, y), axis=0) print(c) """ 输出: [[1 2] [3 4] [5 6]] """
|
对于删除元素,使用索引切片来选择需要保留的元素更加简单。
3 重塑数组
reshape
可以在不更改数据的情况下为数组提供新形状,但是时要注意生成的数组必须和原始数组具有相同数量的元素,如果你从一个有 12 个元素的数组reshape
,你需要确保你的新数组也有总共 12 个元素:
1 2 3 4 5 6 7 8 9 10 11
| arr=np.arange(6) print(arr) arr=arr.reshape(3,2) print(arr) """ 输出: [0 1 2 3 4 5] [[0 1] [2 3] [4 5]] """
|
在这里补充一下numpy以及pandas中axis(轴)的概念,对于二维数组:
1 2 3 4 5
| arr=np.array([[0, 4, 2], [-2, 5, 3]]) """ [[ 0 4 2] [-2 5 3]] """
|
横向(axis=0)对应行,纵向(axis=1)对应列。

在进行操作时,比如前面提到的拼接两个二维数组:
1 2 3 4
| x = np.array([[1, 2], [3, 4]]) y = np.array([[5, 6], [7, 8]]) c=np.concatenate((x, y), axis=0) print(c)
|
axis=0表示顺着axis=0(顺着每一行)操作,结果如下:
1 2 3 4
| [[1 2] [3 4] [5 6] [7 8]]
|
axis=1表示顺着axis=1(顺着每一列)操作,结果如下:
有点古怪对吧,也可以尝试这样理解:axis=0表示竖向操作,横向不变;axis=1表示横向操作,竖向不变。
4 索引和切片
numpy为数组提供了强大的索引功能。你可以像切片python列表一样索引和切片numpy数组。
1 2 3 4 5 6 7 8 9 10 11 12
| data = np.array([1, 2, 3])
print(data[1]) print(data[0:2]) print(data[0::2]) """ 输出: 2 [1 2] [1 3] """
|
对于多维数组,不需要用多个中括号[]
,只需使用逗号,
分隔:
1 2 3
| data=np.array([[1,2],[3,4],[5,6]])
print(data[0,1])
|
一些操作示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| data=np.array([[1,2],[3,4],[5,6]]) print(data[1,:]) print(data[:,1]) print(data[::-1,1])
print(data[(0,1,2),(0,0,1)]) """ 输出: [3 4] [2 4 6] [6 4 2] [1 3 6] """
|
如果想从数组中选择满足特定条件的值,使用numpy很简单:
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
| a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a[a < 5]) """ 输出: [1 2 3 4] """
print(a[a>=5]) """ 输出: [ 5 6 7 8 9 10 11 12] """
print(a[a%2==0]) """ 输出: [ 2 4 6 8 10 12] """
print(a[(a > 4) & (a % 2 == 0)]) print(a[(a < 4) | (a % 2 == 0)]) """ 输出: [ 6 8 10 12] [ 1 2 3 4 6 8 10 12] """
print((a > 4) & (a % 2 == 0)) """ 输出: [[False False False False] [False True False True] [False True False True]] """
|
使用nonzero
可以返回非零元素的索引:
1 2 3 4 5 6 7 8
| x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]]) print(np.nonzero(x)) print(x[np.nonzero(x)]) """ 输出: (array([0, 1, 2, 2]), array([0, 1, 0, 1])) [3 4 5 6] """
|
在此示例中,返回了一个数组元组:每个维度一个。第一个数组表示找到这些值的行索引,第二个数组表示找到这些值的列索引。
除了切片,还可以使用vstack
垂直堆叠、hstack
水平堆叠数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| a1 = np.array([[1, 1], [2, 2]]) a2 = np.array([[3, 3], [4, 4]]) print(np.vstack((a1,a2))) print(np.hstack((a1,a2))) """ 输出: [[1 1] [2 2] [3 3] [4 4]] [[1 1 3 3] [2 2 4 4]] """
|
使用hsplit
或vsplit
,可以将数组水平或垂直拆分为几个形状相同的数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| x = np.arange(1, 25).reshape(2, 12) print(x) print(np.hsplit(x,3)) print(np.vsplit(x,2)) """ 输出: [[ 1 2 3 4 5 6 7 8 9 10 11 12] [13 14 15 16 17 18 19 20 21 22 23 24]] [array([[ 1, 2, 3, 4], [13, 14, 15, 16]]), array([[ 5, 6, 7, 8], [17, 18, 19, 20]]), array([[ 9, 10, 11, 12], [21, 22, 23, 24]])] [array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]), array([[13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]])] """
|
4 视图和副本
视图是一个重要的numpy概念,它是对原始数组的引用,而副本则不是。numpy函数以及索引和切片等操作会尽可能返回视图。这可以节省内存并且速度更快(无需复制数据)。然而,重要的是要意识到:修改视图中的数据也会修改原始数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) print(a)
b1 = a[0, :]
print(np.may_share_memory(a,b1)) print(b1)
b1[0]=99
print(a) """ 输出: [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] True [1 2 3 4] [[99 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] """
|
使用may_share_memory
可用于确定两个数组是彼此的副本还是彼此的视图,这里返回True
,因此修改数组b1会影响原数组a。
使用copy
可以创建副本:
1 2 3 4 5 6 7 8 9 10 11 12 13
| a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) print(a)
b1 = a[0:1, :].copy()
print(np.may_share_memory(a,b1)) """ 输出: [[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]] False """
|
5 基本数组操作
基本操作包括加减乘除:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| data = np.array([1, 2]) ones = np.ones(2, dtype=int) print(data+ones) print(data-ones) print(data*data) print(data/data) """ 输出: [2 3] [0 1] [1 4] [1. 1.] """
|
这里要注意的重要一点是,两个numpy多维数组之间的算术运算不是矩阵乘法。结果仍然返回相同形状的numpy 数组。矩阵乘法需要使用dot
:
1 2 3 4 5 6 7
| data = np.array([1, 2]) ones = np.ones(2, dtype=int) print(np.dot(data,data)) """ 输出: 5 """
|
如果要查找数组中元素的总和,可以使用sum
. 这适用于一维数组、二维数组和更高维度的数组:
1 2 3 4 5 6
| a = np.array([[1, 2, 3, 4],[1, 2, 3, 4]]) print(np.sum(a)) """ 输出: 20 """
|
对于二维和更高维数组,可以指定轴axis进行求和:
1 2 3 4 5 6 7 8
| a = np.array([[1, 2, 3, 4],[1, 2, 3, 4]]) print(np.sum(a,axis=0)) print(np.sum(a,axis=1)) """ 输出: [2 4 6 8] [10 10] """
|
6 广播
numpy操作大部分是按元素进行的,这需要一个操作中的两个数组具有相同的形状。但是,这并不意味着numpy不能操作两个形状不同的数组。numpy提供了在较大的数组上广播较小尺寸的数组的灵活性。比如:
1 2 3 4 5 6 7
| data = np.array([1.0, 2.0]) data *= 1.6 print(data) """ 输出: [1.6 3.2] """
|
numpy理解乘法应该发生在每个单元格上。这个概念叫做广播。广播是一种允许numpy对不同形状的数组执行操作的机制。您的数组的维度必须兼容,例如,当两个数组的维度相等或其中一个为 1 时。如果维度不兼容,将得到一个ValueError
。
具体的规则如下:
如果不满足上述条件,将引发ValueError
异常,以指示数组具有不兼容的形状。举例:
1 2 3 4 5 6 7 8 9 10 11
| x = np.array([[ 0, 0, 0], [10,10,10], [20,20,20]]) y = np.array([1, 2, 3]) print(x+y) """ 输出: [[ 1 2 3] [11 12 13] [21 22 23]] """
|
让我们将前面的代码制作成图表,以帮助我们理解广播。x变量的形状为(3, 3),而y的形状仅为3。但是在 numpy广播中,y的形状转换为1x3;因此,该规则的第二个条件已得到满足。 通过重复将y广播到x的相同形状。+
操作可以按元素应用。

再来看一个广播两个数组的结果:
1 2 3 4 5 6 7 8 9
| x = np.array([[0], [10], [20]]) y = np.array([1,2,3]) print(x+y) """ 输出: [[ 1 2 3] [11 12 13] [21 22 23]] """
|

7 更多有用的数组操作
numpy还有聚合功能。除了min
、max
和sum
之外,还可以用mean
以获得平均值、prod
将元素相乘的结果、std
获得标准偏差、unique
获取唯一元素、.T
转置矩阵等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| arr = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]]) print(np.min(arr)) print(np.max(arr)) print(np.sum(arr)) print(np.mean(arr)) print(np.unique(arr)) print(arr.T) """ 输出: 1 3 18 2.0 [1 2 3] [[1 1 1] [2 2 2] [3 3 3]] """
|
8 反转数组
对数组的反转,除了使用-1
步长完成,也可以用flip
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| arr = np.array([1, 2, 3, 4, 5, 6, 7, 8]) print(np.flip(arr))
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(np.flip(arr,axis=0)) print(np.flip(arr,axis=1)) print(np.flip(arr)) """ 输出: [8 7 6 5 4 3 2 1] [[7 8 9] [4 5 6] [1 2 3]] [[3 2 1] [6 5 4] [9 8 7]] [[9 8 7] [6 5 4] [3 2 1]] """
|
9 重塑和展平多维数组
flatten
和ravel
可以展平多维数组,后者不创建副本,效率更快。
1 2 3 4 5 6 7 8
| x = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) print(x.flatten()) print(x.ravel()) """ 输出: [ 1 2 3 4 5 6 7 8 9 10 11 12] [ 1 2 3 4 5 6 7 8 9 10 11 12] """
|
10 保存和加载numpy对象
有几种方法可以使用numpy保存和加载对象。.npy
和.npz
后缀的文件以允许正确检索数组的方式存储重建ndarray所需的数据、形状、dtype和其他信息,即使文件位于具有不同架构的另一台机器上也是如此。
如果要存储单个ndarray对象,使用np.save
将其存储为.npy
文件,如果要在单个文件中存储多个ndarray对象,使用np.savez
将其保存为.npz
文件。
1 2 3 4 5 6 7 8 9
| a = np.array([1, 2, 3, 4, 5, 6]) np.save('filename', a)
b = np.load('filename.npy') print(b) """ 输出: [1 2 3 4 5 6] """
|
也可以将numpy数组保存为纯文本文件,例如.csv
或.txt
文件:
1 2 3 4 5 6 7 8 9
| csv_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8]) np.savetxt("myfile.csv",csv_arr)
b=np.loadtxt("myfile.csv") print(b) """ 输出: [1. 2. 3. 4. 5. 6. 7. 8.] """
|