深入理解NumPy简明教程---数组3(组合)
前两篇文章对NumPy数组做了基本的介绍,本篇文章对NumPy数组进行较深入的探讨。首先介绍自定义类型的数组,接着数组的组合,最后介绍数组复制方面的问题。
自定义结构数组
通过NumPy也可以定义像C语言那样的结构类型。在NumPy中定义结构的方法如下:
定义结构类型名称;定义字段名称,标明字段数据类型。
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
Unicode
U
Void
V
在定义好结构类型之后,就可以定义以该类型为元素的数组了:
a=array([(“Zhang”,32,65.5),(“Wang”,24,55.2)],dtype=student)
除了在每个元素中依次列出对应字段的数据外,还需要在array函数中最后一个参数指定其所对应的数据类型。
注:例子来源于张若愚的Python科学计算艺术的29页。更多关于dtype的内容请参考《NumPyforBeginner》一书的第二章。
组合函数
这里介绍以不同的方式组合函数。首先创建两个数组:
>>>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]])
水平组合
>>>hstack((a,b)) array([[0,1,2,0,2,4], [3,4,5,6,8,10], [6,7,8,12,14,16]])
也可通过concatenate函数并指定相应的轴来获得这一效果:
>>>concatenate((a,b),axis=1) array([[0,1,2,0,2,4], [3,4,5,6,8,10], [6,7,8,12,14,16]])
垂直组合
>>>vstack((a,b)) array([[0,1,2], [3,4,5], [6,7,8], [0,2,4], [6,8,10], [12,14,16]])
同样,可通过concatenate函数,并指定相应的轴来获得这一效果。
>>>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。顾名思义,就是在数组的第三个轴(即深度)上组合。如下:
>>>dstack((a,b)) array([[[0,0], [1,2], [2,4]], [[3,6], [4,8], [5,10]], [[6,12], [7,14], [8,16]]])
仔细观察,发现对应的元素都组合成一个新的列表,该列表作为新的数组的元素。
行组合
行组合可将多个一维数组作为新数组的每一行进行组合:
>>>one=arange(2) >>>one array([0,1]) >>>two=one+2 >>>two array([2,3]) >>>row_stack((one,two)) array([[0,1], [2,3]])
对于2维数组,其作用就像垂直组合一样。
列组合
列组合的效果应该很清楚了。如下:
>>>column_stack((oned,twiceoned)) array([[0,2], [1,3]])
对于2维数组,其作用就像水平组合一样。
分割数组
在NumPy中,分割数组的函数有hsplit、vsplit、dsplit和split。可将数组分割成相同大小的子数组,或指定原数组分割的位置。
水平分割
>>>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来获得这样的效果:
split(a,3,axis=1)
垂直分割
垂直分割是沿着垂直的轴切分数组:
>>>vsplit(a,3) >>>[array([[0,1,2]]),array([[3,4,5]]),array([[6,7,8]])]
同样,也可通过solit函数并指定轴为1来获得这样的效果:
>>>split(a,3,axis=0)
面向深度的分割
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]]])]
复制和镜像(View)
当运算和处理数组时,它们的数据有时被拷贝到新的数组有时不是。这通常是新手的困惑之源。这有三种情况:
完全不复制
简单的赋值,而不复制数组对象或它们的数据。
>>>a=arange(12) >>>b=a#不创建新对象 >>>bisa#a和b是同一个数组对象的两个名字 True >>>b.shape=3,4#也改变了a的形状 >>>a.shape (3,4) Python传递不定对象作为参考4,所以函数调用不拷贝数组。 >>>deff(x): ...printid(x) ... >>>id(a)#id是一个对象的唯一标识 148293216 >>>f(a) 148293216
视图(view)和浅复制
不同的数组对象分享同一个数据。视图方法创造一个新的数组对象指向同一数据。
>>>c=a.view() >>>cisa False >>>c.baseisa#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]])
切片数组返回它的一个视图:
>>>s=a[:,1:3]#获得每一行1,2处的元素 >>>s[:]=10#s[:]是s的镜像。注意区别s=10ands[:]=10 >>>a array([[0,10,10,3], [1234,10,10,7], [8,10,10,11]])
深复制
这个复制方法完全复制数组和它的数据。
>>>d=a.copy()#创建了一个含有新数据的新数组对象 >>>disa False >>>d.baseisa#d和a现在没有任何关系 False >>>d[0,0]=9999 >>>a array([[0,10,10,3], [1234,10,10,7], [8,10,10,11]])
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。