原文章http://blog.csdn.net/sunny2038/article/details/8907736
自定义结构数组
通过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的内容请参考《NumPy for Beginner》一书的第二章。
组合函数
这里介绍以不同的方式组合函数。首先创建两个数组:
- >>> 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((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((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]])
分割数组
在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(a, 3, axis=1)
垂直分割
垂直分割是沿着垂直的轴切分数组:
- >>> vsplit(a, 3)
- >>> [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
- >>> 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)
当运算和处理数组时,它们的数据有时被拷贝到新的数组有时不是。这通常是新手的困惑之源。这有三种情况<span style="font-family:Courier New,monospace;"><span lang="en-US">:</span></span>
完全不复制
简单的赋值,而不复制数组对象或它们的数据。
- >>> a = arange(12)
- >>> b = a #不创建新对象
- >>> b is a # a和b是同一个数组对象的两个名字
- True
- >>> b.shape = 3,4 #也改变了a的形状
- >>> a.shape
- (3, 4)
Python 传递不定对象作为参考4,所以函数调用不拷贝数组。
- >>> def f(x):
- ... print id(x)
- ...
- >>> id(a) #id是一个对象的唯一标识
- 148293216
- >>> f(a)
- 148293216
视图(view)和浅复制
不同的数组对象分享同一个数据。视图方法创造一个新的数组对象指向同一数据。
- >>> 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]])
- >>> 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]])
深复制
这个复制方法完全复制数组和它的数据。
- >>> 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》