NumPy提供了两种基本的对象:ndarray和ufunc
ndarray是存储单一数据类型的多维数组,ufunc则是能够对数组进行处理的函数
import numpy as np
可以通过给array函数传递Python的序列对象创建数组,如果传递的是多层嵌套的序列,将创建多维数组(例如:变量c):
a = np.array([1,2,3,4])
b = np.array((5,6,7,8))
c = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]])
dtype:数组的元素类型可以通过dtype属性获得,如 c.dtype
数组的元素类型可以通过dtype属性获得。可以通过dtype属性获得。可以通过dtype参数在创建时指定元素类型,如:
d1=np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]],dtype=np.float)
d2=np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]],dtype=np.complex)
运行的结果分别为:
shape:数组的大小可以通过其shape属性获得,如:a.shape。可以通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度,如:c.shape = 4,3(注意从(3,4)改为(4,3)并不是对数组进行转置,只是改变每个轴的大小,数组元素在内存中的位置并没有改变。) c就变成了[[1,2,3],[4,4,5],[6,7,7],[8,9,10]]
c.shape=2,-1 #当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度,因此下面的程序将数组c的shape改为了(2,6)。
reshape:d=a.reshape((2,2)) #使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变。即d变成了
[[1,2],[3,4]],而a还是[1,2,3,4].数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组。如:a[1]=100(将数组a的第2个元素改为100),此时,数组d中的第二个元素也被改变了,变为:[[1,100],[3,4]].
上面的例子都是先创建一个Python序列,然后通过array函数将其转换为数组,这样做效率不高。因此Numpy提供了很多专门用来创建数组的函数。
arange函数类似于python中的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值:
np.arange(0,1,0.1)
结果为:
linspace函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值:
np.linspace(0,1,10) #步长为1/9
np.linspace(0,1,10,endpoint=False) # 步长为1/10
logspace函数和linspace类似,不过它创建等比数列,下面的例子产生1(10^0)到100(10^2)、有20个元素的等比数列:
np.logspace(0,2,20)
zeros()、ones()、empty()可以创建指定形状和类型的数组。
np.empty((2,3),np.int) # 只分配内存,不对其初始化
np.zeros(4,np.float) # 元素类型默认为np.float,因此这里可以省略
此外,zeros_like()、ones_like()、empty_like()等函数可创建与参数数组的形状及类型相同的数组。因此,'zeros_like(a)'和
'zeros(a.shape,a.dtype)'的效果相同。
此外,使用frombuffer,fromstring,fromfile,fromfunction等函数可以从字节序列、文件创建数组,下面以fromfunction为例。
def func(i):
return i%4+1
np.fromfunction(func,(10,))
fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape)。
下面的例子创建一个二维数组表示九九乘法表,输出的数组a中的每个元素a[i,j]都等于func2(i,j):
def func2(i,j):
return (i+1)*(j+1)
a = np.fromfunction(func2,(9,9))
数组元素的存取方法和Python的标准方法相同:
a = np.arange(10)
a[5] # 用整数作为下标可以获取数组中的某个元素
a[3:5],结果为[3,4] # 用范围作为下标获取数组的一个切片,包括a[3]不包括a[5]
a[:5],结果为[0,1,2,3,4] # 省略开始下标,表示从a[0]开始
a[:-1],结果为[0,1,2,3,4,5,6,7,8] # 下标可以使用负数,表示从数组后往前数
a[2:4] = 100,101,结果为[0,1,100,101,4,5,6,7,8,9] # 下标还可以用来修改元素的值
a[1:-1:2],结果为[1,101,5,7] # 范围中的第三个参数表示步长,2表示隔一个元素取一个元素
a[::-1],结果为[9,8,7,6,5,4,101,100,1,0] # 省略范围的开始下标和结束下标,步长为-1,整个数组头尾颠倒
a[5:1:-2],结果为[5,101] # 步长为负数时,开始下标必须大于结束下标
和Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间:
b = a[3:7] ,结果为[101,4,5,6]# 通过下标范围产生一个新的数组b,b和a共享同一块数据空间
b[2] = -10,结果为[101,4,-10,6]# 将b的第3个元素修改为-10,此时a为[0,1,100,101,4,-10,6,7,8,9]
除了使用下标范围存取元素之外,NumPy还提供了两种存取元素的高级方法。
当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以使列表或者数组,使用整数序列作为下标获得的数组不和原始数组共享数据空间。
x = np.arange(10,1,-1) # x为[10,9,8,7,6,5,4,3,2]
x[[3,3,1,8]],结果为[7,7,9,2] # 获取x中的下标为3,3,1,8的4个元素,组成一个新的数组
b = x[np.array([3,3,-3,8])] # 下标可以使负数
b[2]=100,b变为[7,7,100,2],此时x依旧为[10,9,8,7,6,5,4,3,2],由于b和x不共享数据空间,因此x中的值没有改变
x[[3,5,1]] = -1,-2,-3 # 整数序列下标也可以用来修改元素的值,x变为[10,-3,8,-1,6,-2,4,3,2]
x = np.arange(5,0,-1) # x为[5,4,3,2,1]
x[np.array([True,False,True,False,False])],结果为[5,3] # 布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素
x[[True,False,True,False,False]],结果为[5,3] # 如果是布尔列表,下标0,2的元素为True,因此获取x中下标为0,2的元素
x[np.array([True,False,Ture,True,False])] = -1,-2,-3 ,x变为[-1,4,-2,-3,1]# 布尔数组下标也可以用来修改元素
多维数组的存取和一维数组类似,因为多维数组有多个轴,因此它的下标需要用多个值来表示,NumPy采用组元(tuple)
作为数组的下标。
假设需要定义一个结构数组,它的每个元素都有name,age和weigh字段。在NumPy中可以如下定义: