首页 > 代码库 > NumPy基础

NumPy基础

1.1 NumPy 数组对象

NumPy中的ndarray是一个多维数组对象,该对象由两部分组成: ? 实际的数据; ? 描述这些数据的元数据。 大部分的数组操作仅仅修改元数据部分,而不改变底层的实际数据。 NumPy数组的下标也是从0开始的。数组元素的数据类型用专门的对象表示。 我们再次用arange函数创建数组,并获取其数据类型: In: a = arange(5) In: a.dtype Out: dtype(‘int64‘) 数组a的数据类型为int64(在我的机器上是这样),当然如果你使用32位的Python,得到的 结果可能是int32。不论是哪种情形,该数组的数据类型都是整数(64位或32位)。除了数据类 型,数组的维度也是重要的属性。

>>> import array

>>> import numpy

>>> m= array([arange(2),arange(2)])

Traceback (most recent call last): File "", line 1, in

NameError: name ‘arange‘ is not defined

>>> import array

>>> from numpy import *

>>> m= array([arange(2),arange(2)])

>>> m array([[0, 1], [0, 1]])

>>> m.shape (2, 2)

我们将arange函数创建的数组作为列表元素,把这个列表作为参数传给array函数,从而 创建了一个2×2的数组 数组的shape属性 返回一个元组(tuple),元组中的元素即为NumPy数组每一个维度上的大小。上面例子中的数组 是一维的,因此元组中只有一个元素。 选取数组元素

>>> import array

>>> from numpy import *

>>> a =array([[1,2],[3,4]])

>>> a array([[1, 2], [3, 4]])

>>> a[1,2]

Traceback (most recent call last): File "", line 1, in

IndexError: index 2 is out of bounds for axis 1 with size 2

>>> a[1,1]

4

对于数组a,只需要用a[m,n]选取各数组元素,其 中m和n为元素下标

NumPy 数据类型

bool 用一位存储的布尔类型(值为TRUE或FALSE)

inti 由所在平台决定其精度的整数(一般为int32或int64)

int8 整数,范围为?128至127

int16 整数,范围为?32 768至32 767

int32 整数,范围为-2exp31~2exp31-1

int64 整数,范围为-2exp63~2exp63-1

uint8 无符号整数,范围为0至255

uint16 无符号整数,范围为0至65 535

uint32 无符号整数,范围为0至2exp32-1

uint64. 无符号整数,范围为0至2exp64-1

float16 半精度浮点数(16位):其中用1位表示正负号,5位表示指数,10位表示尾数

float32 单精度浮点数(32位):其中用1位表示正负号,8位表示指数,23位表示尾数

float64或float 双精度浮点数(64位):其中用1位表示正负号,11位表示指数,52位表示尾数

complex64 复数,分别用两个32位浮点数表示实部和虚部

complex128或complex. 复数,分别用两个64位浮点数表示实部和虚部

在NumPy中,许多函数的参数中可以指定数据类型,通常这个参数是可选的:

>>> arange(7,dtype= uint16)

array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)

数据类型对象

数据类型对象是numpy.dtype类的实例。如前所述,NumPy数组是有数据类型的,更确切 地说,NumPy数组中的每一个元素均为相同的数据类型。

数据类型对象可以给出单个数组元素在 内存中占用的字节数,即dtype类的itemsize属性:

>>> a=array([[1,2],[3,4]])

>>> a.dtype.itemsize

8

>>> a =arange(7,dtype= uint16)

>>> a.dtype.itemsize

2

字符编码.

整数 i

无符号整数 u

单精度浮点数 f

双精度浮点数 d

布尔值 b

复数 D

字符串 S

unicode字符串 U

void (空) V

>>> from numpy import *

>>> arange(7,dtype(‘D‘))

Traceback (most recent call last): File "", line 1,

in TypeError: unsupported operand type(s) for -: ‘numpy.dtype‘ and ‘int‘

>>> arange(7,dtype=‘D‘)

array([ 0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j, 4.+0.j, 5.+0.j, 6.+0.j])

>>> arange(7,dtype=‘f‘)

array([ 0., 1., 2., 3., 4., 5., 6.], dtype=float32)

dtype类的属性 获取数据类型的字符编码 数组元素的数据类型 str属性可以给出数据类型的字符串表示,该字符串的首个字符表示字节序(endianness), 后面如果还有字符的话,将是一个字符编码,接着一个数字表示每个数组元素存储所需的字节数。 这里,字节序是指位长为32或64的字(word)存储的顺序,包括大端序(big-endian)和小端序 (little-endian)。大端序是将最高位字节存储在最低的内存地址处,用>表示;与之相反,小端序 是将最低位字节存储在最低的内存地址处,用<表示

>>> t=dtype(‘Float64‘)

>>> t.char

‘d‘

>>> t.type <type ‘numpy.float64‘>

>>> t.str

‘<f8‘

1.2 创建自定义数据类型

自定义数据类型是一种异构数据类型,可以当做用来记录电子表格或数据库中一行数据的结 构。 我们用一个长度为40个字 符的字符串来记录商品名称,用一个32位的整数来记录商品的库存数量,最后用一个32位的单精 度浮点数来记录商品价格。下面是具体的步骤。

>>> t = dtype([(‘name‘,str,40),(‘numitems‘,int32),(‘price‘,float32)])

>>> t dtype([(‘name‘, ‘S40‘), (‘numitems‘, ‘<i4‘), (‘price‘, ‘<f4‘)])

>>> t[‘name‘] dtype(‘S40‘)

>>> itemz=array([(‘python‘,40,3.333),(‘php‘,333,2.22)],dtpye=t)

Traceback (most recent call last): File "", line 1, in

TypeError: ‘dtpye‘ is an invalid keyword argument for this function

>>> itemz=array([(‘python‘,40,3.333),(‘php‘,333,2.22)],dtype=t)

>>> itemz[1]

(‘php‘, 333, 2.2200000286102295)

我们创建了一种自定义的异构数据类型,该数据类型包括一个用字符串记录的名字、一个用 整数记录的数字以及一个用浮点数记录的价格。

1.3索引和切片

一维数组的索引和切片

用下标3~7来选取元素3~6 下标0~7,以2为步长选取元素 利用负数下标翻转数组

>>> a =arange(9)

>>> a[3:7]

array([3, 4, 5, 6])

>>> a[:7:2]

array([0, 2, 4, 6])

>>> a[::-1]

array([8, 7, 6, 5, 4, 3, 2, 1, 0])

多维数组的切片和索引

ndarray支持在多维数组上的切片操作。为了方便起见,我们可以用一个省略号(...)来表示遍历剩下的维度。

我们先用arange函数创建一个数组并改变其维度,使之变成一个三维数组:

>>> a=arange(24).reshape(2,3,4)

>>> a.shape (2, 3, 4)

>>> a

array([[

[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11]],

[[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23]

]])

我们可以形象地把它 看做一个两层楼建筑,每层楼有12个房间,并排列成3行4列 各种方法对一个NumPy多维数组进行了切片操作:

选取第1层楼的所有房间

>>> a[0]

array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])

我们还可以这样写,选取第1层楼的所有房间

>>> a[0,:,:]

array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])

多个冒号可以用一个省略号(...)来代替

>>> a[0,...]

array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])

进而可以选取第1层楼、第2排的所有房间

>>> a[0,1]

array([4, 5, 6, 7])

再进一步,我们可以在上面的数组切片中间隔地选定元素

>>> a[0,1,::2]

array([4, 6])

 

我们可以选取所有位于第2行的房间,而不指定楼层和列号

>>> a[:,1]

array([[ 4, 5, 6, 7], [16, 17, 18, 19]])

如果要选取第1层楼的所有位于第2列的房间,在对应的两个维度上指定即可

>>> a[0,:,1]

array([1, 5, 9])

 

 

如果要选取第1层楼的最后一列的所有房间,使用如下代码

>>> a [0,:,-1]

array([ 3, 7, 11])

 

如果要反向选取第1层楼的最后一列的所有房间,使用如下代码

>>> a[0,::-1,-1]

array([11, 7, 3])

在该数组切片中间隔地选定元素:

>>> a[0,::2,-1]

array([ 3, 11])

如果在多维数组中执行翻转一维数组的命令,将在最前面的维度上翻转元素的顺序,

在我们 的例子中将把第1层楼和第2层楼的房间交换:

>>> a[::-1]

array([[[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]], [[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]])

 

1.4改变数组的维度

已经学习了怎样使用reshape函数,现在来学习一下怎样将数组展平 ravel

我们可以用ravel函数完成展平的操作

>>> a

array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]])

>>> a.ravel()

array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]) f

latten 这个函数恰如其名,flatten就是展平的意思,与ravel函数的功能相同。不过,flatten函数会请求分配内存来保存结果,而ravel函数只是返回数组的一个视图(view) >>> a.flatten()

array([ 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函数,我们也可以直接用一个正整数元组来设置数组的维度

>>> a.shape=(6,4)

>>> a

array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]])

这样的做法将直接改变所操作的数组,现在数组b成了一个6×4的多维数组。

transpose 在线性代数中,转置矩阵是很常见的操作。

>>> a.transpose()

array([[ 0, 4, 8, 12, 16, 20], [ 1, 5, 9, 13, 17, 21], [ 2, 6, 10, 14, 18, 22], [ 3, 7, 11, 15, 19, 23]])

 

1.5数组的组合

NumPy数组有水平组合、垂直组合和深度组合等多种组合方式,我们将使用vstack、 dstack、hstack、column_stack、row_stack以及concatenate函数来完成数组的组合。

组合数组:

>>> a=arange(9).reshape(3,3)

>>> a

array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

>>> b=2*a

>>> b

array([[ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])

 

水平组合 我们先从水平组合开始练习。将ndarray对象构成的元组作为参数,传给 hstack函数。

>>> c=hstack((a,b))

>>> c

array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8, 10], [ 6, 7, 8, 12, 14, 16]])

也可以用concatenate函数来实现同样的效果

>>> d=concatenate((a,b),axis=1)

>>> d

array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8, 10], [ 6, 7, 8, 12, 14, 16]])

 

垂直组合

垂直组合同样需要构造一个元组作为参数,只不过这次的函数变成了 vstack。

>>> e=vstack((a,b))

>>> e

array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])

我们将concatenate函数的axis参数设置为0即可实现同样的效果。这也是axis参 数的默认值:

>>> f=concatenate((a,b),axis=0)

>>> f

array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])

 

深度组合 将相同的元组作为参数传给dstack函数,即可完成数组的深度组合。

深度组合,就是将一系列数组沿着纵轴(深度)方向进行层叠组合。 举个例子,有若干张二维平面内的图像点阵数据,我们可以将这些图像数据沿纵轴方向层叠在一起,这就形象地解释了什么 是深度组合。

>>> g=dstack((a,b))

>>> g

array([[[ 0, 0], [ 1, 2], [ 2, 4]], [[ 3, 6], [ 4, 8], [ 5, 10]], [[ 6, 12], [ 7, 14], [ 8, 16]]])

 

列组合

column_stack函数对于一维数组将按列方向进行组合,而对于二维数组,column_stack与hstack的效果是相同的

>>> h=column_stack((a,b))

>>> h

array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8, 10], [ 6, 7, 8, 12, 14, 16]])

 

行组合

当然,NumPy中也有按行方向进行组合的函数,它就是row_stack。

对于两个一维数组,将直接层叠起来组合成一个二维数组。对于二维数组,row_stack与vstack的效果是相同的.

>>> i=row_stack((a,b))

>>> i

array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])

 

1.6数组的分割

>>> a=arange(9).reshape(3,3)

>>> a

array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

 

水平分割

下面的代码将把数组沿着水平方向分割为3个相同大小的子数组:

>>> hsplit(a,3)

[array([[0], [3], [6]]), array([[1], [4], [7]]), array([[2], [5], [8]])]

对同样的数组,等同调用split函数并在参数中指定参数axis=1

>>> split(a,3,axis=1)

[array([[0], [3], [6]]), array([[1], [4], [7]]), array([[2], [5], [8]])]

 

垂直分割 vsplit函数将把数组沿着垂直方向分割:

>>> vsplit(a,3)

[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]

调用split函数并在参数中指定参数axis=0,也可以得到同样的结果

>>> split(a,3,axis=0)

[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]

 

 

深度分割

不出所料,dsplit函数将按深度方向分割数组。我们先创建一个三维数组

>>> c = arange(27).reshape(3, 3, 3)

>>> c

array([[[ 0, 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]]])

>>> dsplit(c,3)

[array([[[ 0], [ 3], [ 6]], [[ 9], [12], [15]], [[18], [21], [24]]]), array([[[ 1], [ 4], [ 7]], [[10], [13], [16]], [[19], [22], [25]]]), array([[[ 2], [ 5], [ 8]], [[11], [14], [17]], [[20], [23], [26]]])]

 

1.7数组的属性

除了shape和dtype属性以外,ndarray对象还有很多其他的属性,在下面一一列出。

ndim属性,给出数组的维数,或数组轴的个数:

>>> a=arange(10).reshape(2,5)

>>> a

array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]])

>>> a.ndim

2

size属性,给出数组元素的总个数,如下所示:

>>> a.size

10

itemsize属性,给出数组中的元素在内存中所占的字节数:

>>> a.itemsize

8

如果你想知道整个数组所占的存储空间,可以用nbytes属性来查看。这个属性的值是itemsize和size属性值的乘积:

>>> a.nbytes

80

T属性的效果和transpose函数一样,如下所示:

>>> a.T

array([[0, 5], [1, 6], [2, 7], [3, 8], [4, 9]])

在NumPy中,复数的虚部是用j表示的。例如,我们可以创建一个由复数构成的数组:

>>> b=array([1.j+1,2.j+3])

>>> b

array([ 1.+1.j, 3.+2.j])

real属性,给出复数数组的实部。如果数组中只包含实数元素,则其real属性将输出原 数组:

>>> b.real

array([ 1., 3.])

imag属性,给出复数数组的虚部:

>>> b.imag

array([ 1., 2.])

如果数组中包含复数元素,则其数据类型自动变为复数型:

>>> b.dtype

dtype(‘complex128‘)

>>> b.dtype.str ‘<c16‘

flat属性将返回一个numpy.flatiter对象,这是获得flatiter对象的唯一方式——我 们无法访问flatiter的构造函数。这个所谓的“扁平迭代器”可以让我们像遍历一维数 组一样去遍历任意的多维数组

>>> c=arange(9).reshape(3,3)

>>> c array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

>>> c.flat

>>> d =c.flat

>>> d

>>> for item in d : print item ...

0 1 2 3 4 5 6 7 8

我们还可以用flatiter对象直接获取一个数组元素:

>>> d[3]

3

 

1.8 数组的转换

使用tolist函数将NumPy数组转换成Python列表。

>>> c

array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

>>> c.tolist

>>> c.tolist()

[[0, 1, 2], [3, 4, 5], [6, 7, 8]]

 

astype函数可以在转换数组时指定数据类型:

>>> c.astype(float)

array([[ 0., 1., 2.], [ 3., 4., 5.], [ 6., 7., 8.]])

NumPy基础