您的位置:首页 > 编程语言 > Python开发

NumPy简明教程(二、数组3)

2014-05-16 12:12 337 查看
前两篇文章对NumPy数组做了基本的介绍,本篇文章对NumPy数组进行较深入的探讨。首先介绍自定义类型的数组,接着数组的组合,最后介绍数组复制方面的问题。


自定义结构数组

通过NumPy也可以定义像C语言那样的结构类型。在NumPy中定义结构的方法如下:

定义结构类型名称;定义字段名称,标明字段数据类型。

[python] view
plaincopy

student= dtype({'names':['name', 'age', 'weight'], 'formats':['S32', 'i','f']}, align = True)

这里student是自定义结构类型的名称,使用dtype函数创建,在第一个参数中,'names'和'formats'不能改变,names中列出的是结构中字段名称,formats中列出的是对应字段的数据类型。S32表示32字节长度的字符串,i表示32位的整数,f表示32位长度的浮点数。最后一个参数为True时,表示要求进行内存对齐。

字段中使用NumPy的字符编码来表示数据类型。更详细的数据类型见下表。
数据类型字符编码
整数i
无符号整数u
单精度浮点数f
双精度浮点数d
布尔值b
复数D
字符串S
UnicodeU
VoidV
在定义好结构类型之后,就可以定义以该类型为元素的数组了:

[python] view
plaincopy

a= array([(“Zhang”, 32, 65.5), (“Wang”, 24, 55.2)], dtype =student)

除了在每个元素中依次列出对应字段的数据外,还需要在array函数中最后一个参数指定其所对应的数据类型。

注:例子来源于张若愚的Python科学计算艺术的29页。更多关于dtype的内容请参考《NumPy
for Beginner》一书的第二章。


组合函数

这里介绍以不同的方式组合函数。首先创建两个数组:

[python] view
plaincopy

>>> 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]])


水平组合

[python] view
plaincopy

>>> hstack((a, b))

array([[ 0, 1, 2, 0, 2, 4],

[ 3, 4, 5, 6, 8, 10],

[ 6, 7, 8, 12, 14, 16]])

也可通过concatenate函数并指定相应的轴来获得这一效果:

[python] view
plaincopy

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

array([[ 0, 1, 2, 0, 2, 4],

[ 3, 4, 5, 6, 8, 10],

[ 6, 7, 8, 12, 14, 16]])


垂直组合

[python] view
plaincopy

>>> vstack((a, b))

array([[ 0, 1, 2],

[ 3, 4, 5],

[ 6, 7, 8],

[ 0, 2, 4],

[ 6, 8, 10],

[12, 14, 16]])

同样,可通过concatenate函数,并指定相应的轴来获得这一效果。

[python] view
plaincopy

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

array([[ 0, 1, 2],

[ 3, 4, 5],

[ 6, 7, 8],

[ 0, 2, 4],

[ 6, 8, 10],

[12, 14, 16]])


深度组合

另外,还有深度方面的组合函数dstack。顾名思义,就是在数组的第三个轴(即深度)上组合。如下:

[python] view
plaincopy

>>> dstack((a, b))

array([[[ 0, 0],

[ 1, 2],

[ 2, 4]],

[[ 3, 6],

[ 4, 8],

[ 5, 10]],

[[ 6, 12],

[ 7, 14],

[ 8, 16]]])

仔细观察,发现对应的元素都组合成一个新的列表,该列表作为新的数组的元素。


行组合

行组合可将多个一维数组作为新数组的每一行进行组合:

[python] view
plaincopy

>>> one = arange(2)

>>> one

array([0, 1])

>>> two = one + 2

>>> two

array([2, 3])

>>> row_stack((one, two))

array([[0, 1],

[2, 3]])

对于2维数组,其作用就像垂直组合一样。


列组合

列组合的效果应该很清楚了。如下:

[python] view
plaincopy

>>> column_stack((oned, twiceoned))

array([[0, 2],

[1, 3]])

对于2维数组,其作用就像水平组合一样。


分割数组

在NumPy中,分割数组的函数有hsplit、vsplit、dsplit和split。可将数组分割成相同大小的子数组,或指定原数组分割的位置。


水平分割

[python] view
plaincopy

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

>>> a

array([[0, 1, 2],

[3, 4, 5],

[6, 7, 8]])

>>> hsplit(a, 3)

[array([[0],

[3],

[6]]),

array([[1],

[4],

[7]]),

array([[2],

[5],

[8]])]

也调用split函数并指定轴为1来获得这样的效果:

[python] view
plaincopy

split(a, 3, axis=1)


垂直分割

垂直分割是沿着垂直的轴切分数组:

[python] view
plaincopy

>>> vsplit(a, 3)

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

同样,也可通过solit函数并指定轴为1来获得这样的效果:

[python] view
plaincopy

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


面向深度的分割

dsplit函数使用的是面向深度的分割方式:

[python] view
plaincopy

>>> 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]]])]


复制和镜像(View)

   当运算和处理数组时,它们的数据有时被拷贝到新的数组有时不是。这通常是新手的困惑之源。这有三种情况:


完全不复制

   简单的赋值,而不复制数组对象或它们的数据。

[python] view
plaincopy

>>> a = arange(12)

>>> b = a #不创建新对象

>>> b is a # a和b是同一个数组对象的两个名字

True

>>> b.shape = 3,4 #也改变了a的形状

>>> a.shape

(3, 4)

   Python 传递不定对象作为参考4,所以函数调用不拷贝数组。

[python] view
plaincopy

>>> def f(x):

... print id(x)

...

>>> id(a) #id是一个对象的唯一标识

148293216

>>> f(a)

148293216


视图(view)和浅复制

   不同的数组对象分享同一个数据。视图方法创造一个新的数组对象指向同一数据。

[python] view
plaincopy

>>> c = a.view()

>>> c is a

False

>>> c.base is a #c是a持有数据的镜像

True

>>> c.flags.owndata

False

>>>

>>> c.shape = 2,6 # a的形状没变

>>> a.shape

(3, 4)

>>> c[0,4] = 1234 #a的数据改变了

>>> a

array([[ 0, 1, 2, 3],

[1234, 5, 6, 7],

[ 8, 9, 10, 11]])

切片数组返回它的一个视图:

[python] view
plaincopy

>>> s = a[ : , 1:3] # 获得每一行1,2处的元素

>>> s[:] = 10 # s[:] 是s的镜像。注意区别s=10 and s[:]=10

>>> a

array([[ 0, 10, 10, 3],

[1234, 10, 10, 7],

[ 8, 10, 10, 11]])


深复制

  这个复制方法完全复制数组和它的数据。

[python] view
plaincopy

>>> d = a.copy() #创建了一个含有新数据的新数组对象

>>> d is a

False

>>> d.base is a #d和a现在没有任何关系

False

>>> d[0,0] = 9999

>>> a

array([[ 0, 10, 10, 3],

[1234, 10, 10, 7],

[ 8, 10, 10, 11]])

参考文献:

《Python科学计算》

《Tentative NumPy Tutorial》

《NumPy for Beginner》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: