本节主要介绍NumPy库ndarray对象的创建与保存方法,以及对其属性的操作方法。
3.2.1 创建ndarray数组
使用NumPy库里的array()函数创建数组,它接受一切序列的对象,包括其他数组,如果传递的是多层嵌套序列,将创建多维数组。示例代码:
>>>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]])
数组Python标准库提供的type()函数可以判断对象的类型。示例代码:
>>>type(a)
numpy.ndarray
返回结果是numpy.ndarray,即创建了NumPy的ndarray对象。
通过Python自带的help()函数或者NumPy库里的info()函数,可以查询NumPy中函数、方法和属性的详细信息。示例代码:
>>>help(np.array)
Help on built-in function array in module numpy.core.multiarray:
array(...)
array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
Create an array.
……
>>>np.info(np.array)
array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
Create an array.
……
3.2.2 数组的属性
NumPy库中提供了很多便捷的属性和方法,以查询数组的相关信息。
1. shape属性与reshape()方法
数组的大小可以通过其shape属性获得,示例代码:
>>>a.shape
(4, )
>>>c.shape
(3, 4)
数组a的shape只有一个元素,因此它是一维数组。而数组c的shape有两个元素,因此它是二维数组。(3, 4)表示数组c的第0轴的长度为3(行),第1轴的长度为4(列)。
使用reshape()函数可以重新定义原数组行和列的值,返回新的数组对象。注意参数中行列个数的乘积要与原数组元素的个数保持一致,此外reshape()函数对原数组没有影响,即不改变原数组的元素位置。示例代码:
>>>arr = np.array([[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]])
>>>arr.reshape(1, 25)
array([[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]])
2. dtype属性与astype()方法
dtype属性返回数组中每个元素的数据类型。如果参数序列元素全是整数,那么所创建数组元素的类型也是整数。示例代码:
>>>arr1 = np.array([1, 2, 3, 4])
>>>arr1.dype
dtype('int32')
int32表示元素的数据类型是整型,元素的位长是32位。NumPy中,同一数组中的元素类型必须统一,经常使用的数据类型如下表所示:
类型名称 | 类型描述 | 表示方法 |
---|---|---|
int | 整型 | int16、int32、int64 |
float | 浮点型 | float16、float32、float64 |
string | 字符串型 | string、unicode |
bool | 布尔型 | True、False |
complex | 复数型 | complex128 |
object | 对象类型 | object |
在创建数组时,可以加入dtype参数限定数据类型的对象。示例代码:
>>>arr2 = np.array([[1, 2, 3, 4], [4, 5, 6, 7], [7, 8, 9, 10]], dtype = float32)
>>>arr2
array([[1., 2., 3., 4.],
[4., 5., 6., 7.],
[7., 8., 9., 10.]])
通过astype()函数可以对数组中每个元素的数据类型进行转化。示例代码:
>>>data3 = [1, 2, 3, 4, 5]
>>>arr3 = np.array(data)
>>>arr3.dtype
dtype('int32')
>>>float_arr = arr1.astype(np.float32)
>>>float_arr.dtype
dtype('float32')
与reshape()输出结果不同,astype()函数改变了原数组元素的属性,而reshape()方法对原数组保持不变。
3. size属性和ndim属性
size属性返回数组元素的个数;ndim属性返回数组的维度。示例代码:
>>>arr4 = np.array([[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]])
>>>arr4.size
25
>>>arr4.ndim
2
3.3.3 其他方式创建数组
上面的例子都是先创建一个序列,然后通过array函数将其转换为数组,这样做显然效率不高,因此NumPy提供了许多专门用来创建数组的函数。
arange()函数类似于Python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值。示例代码:
>>>np.arange(0, 1, 0.1)
array([ 0., 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
linspace()函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值,示例代码:
>>>np.linspace(0, 1, 12)
array([ 0. , 0.09090909, 0.18181818, 0.27272727, 0.36363636,
0.45454545, 0.54545455, 0.63636364, 0.72727273, 0.81818182,
0.90909091, 1. ])
logspace()函数和linspace()函数类似,不过它创建等比数列,指定开始值和终值是10的幂值,下面的例子产生1(10^0)到100(10^2)、有20个元素的等比数列,示例代码:
>>>np.logspace(0, 2, 20)
array([ 1. , 1.27427499, 1.62377674, 2.06913808,
2.6366509 , 3.35981829, 4.2813324 , 5.45559478,
6.95192796, 8.8586679 , 11.28837892, 14.38449888,
18.32980711, 23.35721469, 29.76351442, 37.92690191,
48.32930239, 61.58482111, 78.47599704, 100. ])
zeros()和ones()函数是根据给定的形状参数(shape),分别返回一个元素全部为0的数组或者全部为1的数组。示例代码:
>>>np.zeros((2, 3))
array([[ 0., 0., 0.],
[ 0., 0., 0.]])
>>>np.ones((3, 2))
array([[ 1., 1.],
[ 1., 1.],
[ 1., 1.]])
eye()函数返回一个对角线元素为1,其他元素为0的二维数组。示例代码:
>>>np.eye(3)
array([[ 1., 0., 0.],
[ 0., 1., 0.],
[ 0., 0., 1.]])
full()函数,可以根据给定的行列参数及指定值,创建元素统一为指定值的数组。示例代码:
>>>np.full((2, 3), 7)
array([[ 7., 7., 7.],
[ 7., 7., 7.]])
NumPy库中random模块提供大量的随机数相关函数,返回不同分布或序列的随机数元素数组,各函数名及功能如下表所示:
函数名 | 函数功能 |
---|---|
rand() | 产生0到1之间的随机浮点数,它的所有参数用于指定所产生的数组的形状 |
randn() | 产生标准正态分布的随机数,参数含义与rand()相同 |
randint() | 产生指定范围的随机整数,包括起始值,但不包括终值 |
示例代码:
>>>np.random.rand(4, 3)
array([[ 0.06656639, 0.98441457, 0.41562723],
[ 0.55361735, 0.28230227, 0.9850847 ],
[ 0.87730206, 0.15071579, 0.34109152],
[ 0.18123692, 0.82597656, 0.10593983]])
>>>np.random.randn(4, 3)
array([[ 1.65730492, 0.42038461, -0.88787035],
[ 0.77341888, -0.402507 , -0.39044014],
[-0.18054801, 1.18733182, -0.87334895],
[-0.12622612, -2.13722455, -0.29762197]])
>>>np.random.randint(0, 10, (4, 3))
array([[4, 7, 1],
[3, 0, 4],
[6, 2, 5],
[9, 9, 2]])
3.2.4 数组存取
numpy.load和numpy.save函数以NumPy专用的二进制类型保存数据,这两个函数会自动处理元素类型和shape等信息,使用它们读写数组非常方便,但是numpy.save输出的文件很难和其它语言编写的程序读入,示例代码:
>>>arr = np.arange(12).reshape((4, 3)) #产生从0到11的序列,并以4行3列的方式返回给arr
>>>arr
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
>>>np.save("arr.npy", arr) #以arr.npy的文件名保存数组arr
>>>s = np.load("arr.npy") #读取arr.npy文件并返回给s
>>>s
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
此外numpy.savez函数可以将多个数组保存到一个文件,savez(函数的一个参数是文件名,其后的参数都是需要保存的数组,也可以使用关键字参数为数组起一个名字,以非关键字参数传递的数组会自动起名为arr_0、arr_1、…。savez()函数输出一个压缩文件(扩展名为npz),其中每个文件都是一个save函数保存的npy文件,文件名对应于数组名。load函数自动识别npz文件,并且返回一个类似于字典的对象,可以通过数组名作为关键字获取数组的内容,示例代码:
>>>a = np.array([[1, 2, 3],[4, 5, 6]])
>>>b = np.arange(0, 1.0, 0.1)
>>>c = np.random.randn(4, 4)
>>>np.savez("save.npz", a, b, k_c=c)
>>>s = np.load("save.npz")
>>>s["arr_0"] #数组a
array([[1, 2, 3],
[4, 5, 6]])
>>>s["arr_1"] #数组b
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
>>>s["k_c"] #数组c
array([[-0.02499583, -0.42932972, -0.87850541, 1.22665883],
[ 0.84368525, 1.13089567, -1.06471769, -1.24888949],
[-0.04705682, -0.27626076, -0.71521138, 1.17094273],
[-0.45764641, 0.16822594, 0.41377784, 0.57015392]])
如下图所示,ipython文件列表存在与程序文件(Untitled.ipynb)同一目录级别的arr.npy和save.npz文件,其中arr.npy保存着数组arr的内容。如果用解压软件打开save.npz文件,会发现其中有三个文件:arr_0.npy,arr_1.npy,k_c.npy,分别保存着数组a,b,c的内容。
ndarray数组除了保存为NumPy自带的格式,也可以保存为txt格式,与此同时,NumPy也可以加载csv或者txt文件以转换成ndarray形式数据。示例代码:
>>>arr = np.genfromtxt("myfile.csv", delimiter = ',', dtype = "string") #从myfile.csv中导入数据,以逗号为间隔符,类型为string型
>>>np.savetxt("myarray.txt", arr, delimiter = ' ') #将arr保存到myarray.txt文件,以空格为间隔符