NumPy 的详细教程(官网手册翻译)
基础篇
NumPy 的主要对象是同种元素的多维数组。这是一个所有的元素都是一种类型、通过一个正
整数元组索引的元素表格(通常是元素是数字)。在 NumPy 中维度(dimensions)叫做轴
(axes),轴的个数叫做秩(rank)。
例如,在 3D 空间一个点的坐标 [1, 2, 3] 是一个秩为 1 的数组,因为它只有一个轴。那个
轴长度为 3.又例如,在以下例子中,数组的秩为 2(它有两个维度).第一个维度长度为 2,第二个
维度长度为 3.
1. [[ 1., 0., 0.],
2. [ 0., 1., 2.]]
NumPy 的数组类被称作 ndarray。通常被称作数组。注意 numpy.array 和标准 Python 库类
array.array 并不相同,后者只处理一维数组和提供少量功能。更多重要 ndarray 对象属性有:
ndarray.ndim
数组轴的个数,在 python 的世界中,轴的个数被称作秩
ndarray.shape
数组的维度。这是一个指示数组在每个维度上大小的整数元组。例如一个 n 排 m 列的矩
阵,它的 shape 属性将是(2,3),这个元组的长度显然是秩,即维度或者 ndim 属性
ndarray.size
数组元素的总个数,等于 shape 属性中元组元素的乘积。
ndarray.dtype
一个用来描述数组中元素类型的对象,可以通过创造或指定 dtype 使用标准 Python 类
型。另外 NumPy 提供它自己的数据类型。
ndarray.itemsize
数组中每个元素的字节大小。例如,一个元素类型为 float64 的数组 itemsiz 属性值为
8(=64/8),又如,一个元素类型为 complex32 的数组 item 属性为 4(=32/8).
ndarray.data
包含实际数组元素的缓冲区,通常我们不需要使用这个属性,因为我们总是通过索引来
使用数组中的元素。
一个例子 1
1. >>> from numpy import *
2. >>> a = arange(15).reshape(3, 5)
3. >>> a
4. array([[ 0, 1, 2, 3, 4],
5. [ 5, 6, 7, 8, 9],
6. [10, 11, 12, 13, 14]])
7. >>> a.shape
8. (3, 5)
9. >>> a.ndim
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
2
>>> a.dtype.name
'int32'
>>> a.itemsize
4
>>> a.size
15
>>> type(a)
numpy.ndarray
>>> b = array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
numpy.ndarray
创建数组
有好几种创建数组的方法。
例如,你可以使用 array 函数从常规的 Python 列表和元组创造数组。所创建的数组类型由
原序列中的元素类型推导而来。
1. >>> from numpy import *
2. >>> a = array( [2,3,4] )
3. >>> a
4. array([2, 3, 4])
5. >>> a.dtype
6. dtype('int32')
7. >>> b = array([1.2, 3.5, 5.1])
8. >>> b.dtype
9. dtype('float64') 一个常见的错误包括用多个数值参数调用`arr
ay`而不是提供一个由数值组成的列表作为一个参数。
10.
11.
12.
13.
>>> a = array(1,2,3,4) # WRONG
>>> a = array([1,2,3,4]) # RIGHT
数组将序列包含序列转化成二维的数组,序列包含序列包含序列转化成三维数组等等。
1. >>> b = array( [ (1.5,2,3), (4,5,6) ] )
2. >>> b
3. array([[ 1.5, 2. , 3. ],
4. [ 4. , 5. , 6. ]])
数组类型可以在创建时显示指定
1. >>> c = array( [ [1,2], [3,4] ], dtype=complex )
2. >>> c
3. array([[ 1.+0.j, 2.+0.j],
4. [ 3.+0.j, 4.+0.j]])
通常,数组的元素开始都是未知的,但是它的大小已知。因此,NumPy 提供了一些使用占位
符创建数组的函数。这最小化了扩展数组的需要和高昂的运算代价。
函数 function 创建一个全是 0 的数组,函数 ones 创建一个全 1 的数组,函数 empty
创建一个内容随机并且依赖与内存状态的数组。默认创建的数组类型(dtype)都是 float64。
1. >>> zeros( (3,4) )
2. array([[0., 0., 0., 0.],
3. [0., 0., 0., 0.],
4. [0., 0., 0., 0.]])
5. >>> ones( (2,3,4), dtype=int16 ) # dtype c
an also be specified
6. array([[[ 1, 1, 1, 1],
7. [ 1, 1, 1, 1],
8. [ 1, 1, 1, 1]],
9. [[ 1, 1, 1, 1],
10.
11.
12.
13.
6.55490914e‐260],
00000000e+000]])
[ 1, 1, 1, 1],
[ 1, 1, 1, 1]]], dtype=int16)
>>> empty( (2,3) )
array([[ 3.73603959e‐262, 6.02658058e‐154,
14.
[ 5.30498948e‐313, 3.14673309e‐307, 1.
为了创建一个数列,NumPy 提供一个类似 arange 的函数返回数组而不是列表:
1. >>> arange( 10, 30, 5 )
2. array([10, 15, 20, 25])
3. >>> arange( 0, 2, 0.3 ) # it accepts floa
t arguments
4. array([ 0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
当 arange 使用浮点数参数时,由于有限的浮点数精度,通常无法预测获得的元素个数。因
此,最好使用函数 linspace 去接收我们想要的元素个数来代替用 range 来指定步长。
其它函数 array, zeros, zeros_like, ones, ones_like, empty, empty_like, arange, linspace,
rand, randn, fromfunction, fromfile 参考:NumPy 示例
打印数组
当你打印一个数组,NumPy 以类似嵌套列表的形式显示它,但是呈以下布局:
最后的轴从左到右打印
次后的轴从顶向下打印
剩下的轴从顶向下打印,每个切片通过一个空行与下一个隔开
一维数组被打印成行,二维数组成矩阵,三维数组成矩阵列表。
1. >>> a = arange(6) # 1d array
2. >>> print a
3. [0 1 2 3 4 5]
4. >>>
5. >>> b = arange(12).reshape(4,3) # 2d array
6. >>> print b
7. [[ 0 1 2]
8. [ 3 4 5]
9. [ 6 7 8]
10.
11.
12.
[ 9 10 11]]
>>>
>>> c = arange(24).reshape(2,3,4) # 3d arr
ay
13.
14.
15.
16.
17.
18.
19.
20.
>>> print c
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]
查看形状操作一节获得有关 reshape 的更多细节
如果一个数组用来打印太大了,NumPy 自动省略中间部分而只打印角落
1. >>> print arange(10000)
2. [ 0 1 2 ..., 9997 9998 9999]
3. >>>
4. >>> print arange(10000).reshape(100,100)
5. [[ 0 1 2 ..., 97 98 99]
6. [ 100 101 102 ..., 197 198 199]
7. [ 200 201 202 ..., 297 298 299]
8. ...,
9. [9700 9701 9702 ..., 9797 9798 9799]
10.
11.
[9800 9801 9802 ..., 9897 9898 9899]
[9900 9901 9902 ..., 9997 9998 9999]]
禁用 NumPy 的这种行为并强制打印整个数组,你可以设置 printoptions 参数来更改打印选
项。
>>> set_printoptions(threshold='nan')
基本运算
数组的算术运算是按元素的。新的数组被创建并且被结果填充。
1. >>> a = array( [20,30,40,50] )
2. >>> b = arange( 4 )
3. >>> b
4. array([0, 1, 2, 3])
5. >>> c = a‐b
6. >>> c
7. array([20, 29, 38, 47])
8. >>> b**2
9. array([0, 1, 4, 9])
10.
>>> 10*sin(a)
11.
array([ 9.12945251, ‐9.88031624, 7.4511316 , ‐2.
62374854])
12.
13.
>>> a<35
array([True, True, False, False], dtype=bool)
不像许多矩阵语言,NumPy 中的乘法运算符 * 指示按元素计算,矩阵乘法可以使用 dot 函
数或创建矩阵对象实现(参见教程中的矩阵章节)
1. >>> A = array( [[1,1],
2. ... [0,1]] )
3. >>> B = array( [[2,0],
4. ... [3,4]] )
5. >>> A*B # elementwise product
6. array([[2, 0],
7. [0, 4]])
8. >>> dot(A,B) # matrix product
9. array([[5, 4],
10.
[3, 4]])
有些操作符像 += 和 *= 被用来更改已存在数组而不创建一个新的数组。
1. >>> a = ones((2,3), dtype=int)
2. >>> b = random.random((2,3))
3. >>> a *= 3
4. >>> a
5. array([[3, 3, 3],
6. [3, 3, 3]])
7. >>> b += a
8. >>> b
9. array([[ 3.69092703, 3.8324276 , 3.0114541 ],
10.
11.
[ 3.18679111, 3.3039349 , 3.37600289]])
>>> a += b # b is c
onverted to integer type
12.
13.
14.
>>> a
array([[6, 6, 6],
[6, 6, 6]])
当运算的是不同类型的数组时,结果数组和更普遍和精确的已知(这种行为叫做 upcast)。
1. >>> a = ones(3, dtype=int32)
2. >>> b = linspace(0,pi,3)
3. >>> b.dtype.name
4. 'float64'
5. >>> c = a+b
6. >>> c
7. array([ 1. , 2.57079633, 4.14159265])
8. >>> c.dtype.name
9. 'float64'
10.
11.
12.
>>> d = exp(c*1j)
>>> d
array([ 0.54030231+0.84147098j, ‐0.84147098+0.540
30231j,
‐0.54030231‐0.84147098j])
>>> d.dtype.name
'complex128' 许多非数组运算,如计算数组所有元素之
和,被作为 ndarray 类的方法实现
>>> a = random.random((2,3))
>>> a
array([[ 0.6903007 , 0.39168346, 0.16524769],
[ 0.48819875, 0.77188505, 0.94792155]])
>>> a.sum()
3.4552372100521485
>>> a.min()
0.16524768654743593
>>> a.max()
0.9479215542670073
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
这些运算默认应用到数组好像它就是一个数字组成的列表,无关数组的形状。然而,指定
axis 参数你可以吧运算应用到数组指定的轴上:
1. >>> b = arange(12).reshape(3,4)
2. >>> b
3. array([[ 0, 1, 2, 3],
4. [ 4, 5, 6, 7],
5. [ 8, 9, 10, 11]])
6. >>>
7. >>> b.sum(axis=0) # sum of each
column
8. array([12, 15, 18, 21])
9. >>>
10.
of each row
11.
12.
array([0, 4, 8])
>>>
>>> b.min(axis=1) # min