NUMPY简介¶
NumPy是使用Python进行科学计算的基础包。它包含如下内容:
- 一个强大的N维数组对象
- 复杂的(广播)功能
- 用于集成C / C ++和Fortran代码的工具
- 有用的线性代数,傅里叶变换和随机数功能
除了明显的科学用途外,NumPy还可以用作通用数据的高效多维容器。可以定义任意数据类型。这使NumPy能够无缝快速地与各种数据库集成。
新手入门¶
入门条件¶
在阅读本教程之前,您应该了解一些Python。如果您想重温记忆,请查看Python教程。
如果您希望使用本教程中的示例,则还必须在计算机上安装某些软件。有关说明,请参阅 http://scipy.org/install.html。
基础知识¶
NumPy的主要对象是同构多维数组。它是一个元素表(通常是数字),都是相同的类型,由正整数元组索引。在NumPy维度中称为轴。
例如,3D空间中的点的坐标[1, 2, 1]具有一个轴。该轴有3个元素,所以我们说它的长度为3.在下面所示的例子中,数组有2个轴。第一轴的长度为2,第二轴的长度为3。
import numpy as np
a=np.array([
[1,2,3],
[4,5,6]
])
print('第一个轴的长度是:{}'.format(len(a)))
print('第二个轴的长度是:{}'.format(len(a[0])))
numpy的数组类是ndarray,它的别名是array。请注意,numpy.array这与标准Python库类array.array不同,后者仅处理一维数组并提供较少的功能。ndarray对象更重要的属性是:
ndarray.ndim¶
数组的轴(维度)的个数。在Python世界中,维度的数量被称为rank。
ndarray.shape¶
数组的维度。这是一个整数的元组,表示每个维度中数组的大小。对于有n行和m列的矩阵,shape将是(n,m)。因此,shape元组的长度就是rank或维度的个数 ndim。
ndarray.size¶
数组元素的总数。这等于shape的元素的乘积。
ndarray.dtype¶
一个描述数组中元素类型的对象。可以使用标准的Python类型创建或指定dtype。另外NumPy提供它自己的类型。例如numpy.int32、numpy.int16和numpy.float64。
ndarray.itemsize¶
数组中每个元素的字节大小。例如,元素为 float64 类型的数组的 itemsize 为8(=64/8),而 complex32 类型的数组的 itemsize 为4(=32/8)。它等于 ndarray.dtype.itemsize 。
ndarray.data¶
该缓冲区包含数组的实际元素。通常,我们不需要使用此属性,因为我们将使用索引访问数组中的元素。
下面举了两个例子,注意对比理解属性的变化
import numpy as np
a=np.array([
[1,2,3],
[4,5,6]
])
print('ndarray.ndim:',a.ndim)
print('ndarray.shape:',a.shape)
print('ndarray.size:',a.size)
print('ndarray.dtype:',a.dtype)
print('ndarray.itemsize:',a.itemsize)
import numpy as np
a=np.arange(32).reshape(4,4,2)
print(a)
print('ndarray.ndim:',a.ndim)
print('ndarray.shape:',a.shape)
print('ndarray.size:',a.size)
print('ndarray.dtype:',a.dtype)
print('ndarray.itemsize:',a.itemsize)
import numpy as np
a=np.array([1,2,3,4,5])
print('a is :',a)
print('a\'s type is :',type(a))
print('a\'s dtype is :',a.dtype)
一个常见的错误在于使用多个数值参数调用 array 函数,而不是提供一个数字列表(List)作为参数。
a = np.array(1,2,3,4) # WRONG
a = np.array([1,2,3,4]) # RIGHT
用numpy生成占位符¶
通常,数组的元素最初是未知的,但它的大小是已知的。因此,NumPy提供了几个函数来创建具有初始占位符内容的数组。这就减少了数组增长的必要,因为数组增长的操作花费很大。
函数 zeros 创建一个由0组成的数组,函数 ones 创建一个由1数组的数组,函数 empty 内容是随机的并且取决于存储器的状态。默认情况下,创建的数组的dtype是 float64。
import numpy as np
a=np.zeros((4,2))
b=np.ones((4,2))
c=np.empty((4,2))
print('result of np.zeros((4,2)) is :\n',a,'\n')
print('result of np.ones((4,2)) is :\n',b,'\n')
print('result of np.empty((4,2)) is :\n',c,'\n')
使用arange函数创建¶
要创建数字序列,NumPy提供了一个类似于 range 的函数,该函数返回数组而不是列表。
import numpy as np
a=np.arange(10,30,5)#10代表起始数,30代表终止数,5代表步长
print('a is :',a)
print('a\'s type is :',type(a))
print('a\'s dtype is :',a.dtype)
当 arange 与浮点参数一起使用时,由于浮点数的精度是有限的,通常不可能预测获得的元素数量。出于这个原因,通常最好使用函数 linspace ,它接收我们想要的元素数量而不是步长作为参数:
from numpy import pi
a=np.linspace(0,2,9)#从0到2之间取9个数
b=np.linspace( 0, 2*pi, 10 )# 在取值数量很多时适用
c=np.sin(b)
print('a is :\n',a,'\n')
print('a\'s type is :',type(a),'\n')
print('a\'s dtype is :',a.dtype,'\n')
print('b is :\n',b,'\n')
print('b\'s type is :',type(b),'\n')
print('b\'s dtype is :',b.dtype,'\n')
print('c is :\n',c,'\n')
print('c\'s type is :',type(c),'\n')
print('c\'s dtype is :',c.dtype,'\n')
另见:¶
array, zeros, zeros_like, ones, ones_like, empty, empty_like, arange, linspace, numpy.random.rand, numpy.random.randn, fromfunction, fromfile
打印数组¶
当你打印数组时,NumPy以与嵌套列表类似的方式显示它,但是具有以下布局:
- 最后一个轴从左到右打印,
- 倒数第二个从上到下打印,
- 其余的也从上到下打印,每个切片与下一个用空行分开。 一维数组被打印为行、二维为矩阵和三维为矩阵列表。
a = np.arange(6)
print('一维打印')
print(a)#一维打印
b = np.arange(12).reshape(4,3)
print('二维打印')
print(b)#二维打印
c = np.arange(24).reshape(2,3,4)
print('三维打印')
print(c)#三维打印
#如果数组太大而无法打印,NumPy将自动跳过数组的中心部分并仅打印角点:
print(np.arange(10000))
print(np.arange(10000).reshape(100,100))
#要禁用此行为并强制NumPy打印整个数组,你可以使用 set_printoptions 更改打印选项。
np.set_printoptions(threshold=np.nan)
基本操作¶
在数组元素上进行数学运算,产生新的数组。
import numpy as np
a=np.array([1,2,3,4])
b=np.arange(4)
c=a-b
d=a**2
e=10*np.sin(a)
f=a<3
print('a is:\n',a,'\n')
print('b is:\n',b,'\n')
print('c(a-b) is:\n',c,'\n')
print('d(a**2) is:\n',d,'\n')
print('e(10*np.sin(a)) is:\n',e,'\n')
print('c(a<3) is:\n',f,'\n')
与许多矩阵语言不同,乘法运算符 * 的运算在NumPy数组中是元素级别的,也称为哈达马积。矩阵乘积可以使用@运算符(在python> = 3.5中)或dot函数或方法执行:
a=np.array( [[1,1],[0,1]])
b=np.array( [[2,0],[3,4]])
c=a*b#元素乘积
d=a@b#矩阵乘积
e=a.dot(b)#另一种矩阵乘积的方式
print('a is:\n',a,'\n')
print('b is:\n',b,'\n')
print('c(a*b) is:\n',c,'\n')
print('d(a@b) is:\n',d,'\n')
print('e(a.dot(b)) is:\n',e,'\n')
某些操作(例如+=和*=)适用于修改现有数组,而不是创建新数组。
a = np.ones((2,3), dtype=int)
print('a is :\n',a,'\n')
a *= 3
print('a *= 3 is :\n',a,'\n')
b = np.random.random((2,3))
print('b is :\n',b,'\n')
b +=a
print('b +=a is :\n',b,'\n')
a += b # b不会自动转换成int类型,会报错
当使用不同类型的数组操作时,结果数组的类型对应于更一般或更精确的数组(称为向上转换的行为)。
a = np.ones(3, dtype=np.int32)
b = np.linspace(0,pi,3)
c = a+b
d = np.exp(c*1j)
print('a.dtype.name is ',a.dtype.name)
print('b.dtype.name is ',b.dtype.name)
print('c.dtype.name is ',c.dtype.name)
print('d.dtype.name is ',d.dtype.name)
许多一元运算,例如计算数组中所有元素的总和,都是作为 ndarray 类的方法实现的。
a = np.random.random((2,3))
sum=a.sum()
min=a.min()
max=a.max()
print('a is:\n ',a,'\n')
print('sum(a.sum()) is:\n',sum,'\n')
print('min(a.min()) is:\n',min,'\n')
print('max(a.max()) is:\n',max,'\n')
默认情况下,这些操作适用于数组,就好像它是数字列表一样,无论其形状如何。但是,通过指定 axis 参数,你可以沿着数组的指定轴应用操作:
a = np.arange(12).reshape(3,4)
sum=a.sum(axis=0)# sum of each column
min=a.min(axis=1) # min of each row
cumsum=a.cumsum(axis=1)# cumulative sum along each row
print('a is:\n ',a,'\n')
print('sum(a.sum()) is:\n',sum,'\n')
print('min(a.min()) is:\n',min,'\n')
print('cumsum(a.cumsum()) is:\n',cumsum,'\n')
通用函数¶
NumPy提供熟悉的数学函数,例如sin,cos和exp。在NumPy中,这些被称为“通用函数”(ufunc)。在NumPy中,这些函数在数组上以元素方式运行,产生一个数组作为输出。
a=np.arange(3)
b=np.exp(a)
c=np.sqrt(a)
print('a is:\n ',a,'\n')
print('b is:\n ',b,'\n')
print('c is:\n ',c,'\n')
另请参见: all, any, apply_along_axis, argmax, argmin, argsort, average, bincount, ceil, clip, conj, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, inv, lexsort, max, maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sort, std, sum, trace, transpose, var, vdot, vectorize, where
索引、切片和迭代¶
一维数组可以被索引,切片和迭代,就像列出和其他Python序列一样。
a = np.arange(10)**3
print('a is:\n ',a,'\n')
print('a[2] is:',a[2],'\n')
print('a[2:5] is:',a[2:5],'\n')
a[:6:2] = -1000# equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
print('a is:\n ',a,'\n')
print('a[ : :-1] is:\n ',a[ : :-1],'\n')#倒排a
for i in a:
print(i**(1/3.))#由于jupyter的原因,这里报错了
多维(Multidimensional) 数组每个轴可以有一个索引。 这些索在元组中以逗号分隔给出:
def f(x,y):
return 10*x+y
a = np.fromfunction(f,(5,4),dtype=int)
print('a is:\n ',a,'\n')
print('a[2,3] is ',a[2,3])
print('a[0:5,1] is ',a[0:5,1])# each row in the second column of a
print('a[ : ,1] is ',a[ : ,1]) # equivalent to the previous example
print('a[1:3, : ] is \n',a[1:3, : ])# each column in the second and third row of b
当提供比轴数更少的索引时,缺失的索引被认为是一个完整切片 :
a[-1]
b[i] 方括号中的表达式 i 被视为后面紧跟着 : 的多个实例,用于表示剩余轴。NumPy也允许你使用三个点写为 b[i,...]。
三个点( ... )表示产生完整索引元组所需的冒号。例如,如果 x 是rank为的5数组(即,它具有5个轴),则
- x[1,2,...] 等于 x[1,2,:,:,:]
- x[...,3] 等效于 x[:,:,:,:,3]
- x[4,...,5,:] 等效于 x[4,:,:,5,:]
c = np.array( [[[ 0, 1, 2], # a 3D array (two stacked 2D arrays)
[ 10, 12, 13]],
[[100,101,102],
[110,112,113]]])
print('c.shape is ',c.shape,'\n')
print('c[1,...] is :\n',c[1,...],'\n') # same as c[1,:,:] or c[1]
print('c[...,2] is :\n',c[...,2],'\n') # same as c[:,:,2]
迭代(Iterating) 多维数组是相对于第一个轴完成的:
for row in c:
print(row,'\n')
但是,如果想要对数组中的每个元素执行操作,可以使用 flat 属性,该属性是数组中所有元素的迭代器:
for element in c.flat:
print(element)