Numpy 系列(九)- 结构化数组

  简介 

以前咱们操做Numpy的数组时,都是经过索引来操做的。针对二维数组,使用索引能够完成对行、列的操做。可是这是很是不直观的。能够把二维数组想象成一个excel表格,若是表格没有列名,操做起来会很是麻烦,针对这种状况,Numpy提供告终构化数组用来操做每列数据。python

以前咱们操做Numpy的数组时,都是经过索引来操做的。针对二维数组,使用索引能够完成对行、列的操做。可是这是很是不直观的。能够把二维数组想象成一个excel表格,若是表格没有列名,操做起来会很是麻烦,针对这种状况,Numpy提供告终构化数组用来操做每列数据。数组

来看一个示例函数

x = np.array([('Bob', 18, 2000.0),('Tom', 23, 4000.0)],dtype=[('name', 'S10'), ('age', np.int_), ('incom', np.float_)])
x
Out[245]: 
array([(b'Bob', 18, 2000.), (b'Tom', 23, 4000.)],
      dtype=[('name', 'S10'), ('age', '<i4'), ('incom', '<f8')])
x.shape
Out[246]: (2,)
row = x[0]
row
Out[248]: (b'Bob', 18, 2000.)
col = x['name']
col
Out[250]: array([b'Bob', b'Tom'], dtype='|S10')

上面咱们建立了一个二维数组,行数为2,列数为3,其中每列的类型分别是长度为10或者更小的字符串、32位整数、64位浮点数。以后分别使用数字索引访问了第一行数据获得row,以及使用名称索引访问了第一列数据获得col。ui

须要注意的是,无论是row仍是col,获取到的都是只是视图,因此更改结构化数组x时,对应的视图也会发生改变。this

x['name'] = ['Bob01', 'Tom01']
x
Out[252]: 
array([(b'Bob01', 18, 2000.), (b'Tom01', 23, 4000.)],
      dtype=[('name', 'S10'), ('age', '<i4'), ('incom', '<f8')])
row
Out[253]: (b'Bob01', 18, 2000.)
col
Out[254]: array([b'Bob01', b'Tom01'], dtype='|S10')

构建结构化数组

经过dtype对象定义一个结构化数组。使用参数(如提供给dtype函数关键字或dtype对象构造函数自己)经过四种可选方法之一指定记录结构。此参数必须是如下之一:string,tuple,list,或 dictionary。spa

字符串参数excel

在这种状况下,构造函数须要一个逗号分隔的类型说明符列表,可选地包含额外的形状信息。字段被赋予默认名称'f0','f1','f2'等。类型说明符能够采用4种不一样的形式:code

a) b1, i1, i2, i4, i8, u1, u2, u4, u8, f2, f4, f8, c8, c16, a<n>
   (表明 bytes, ints, unsigned ints, floats, complex and
    fixed length strings of specified byte lengths)b) int8,...,uint8,...,float16, float32, float64, complex64, complex128
   (this time with bit sizes)c) older Numeric/numarray type specifications (e.g. Float32).
   不推荐使用!d) Single character type specifiers (e.g H for unsigned short ints).
   通常也避免使用!

示例以下:orm

x = np.zeros(3, dtype='3int8, float32, (2,3)float64')
x
Out[256]: 
array([([0, 0, 0], 0., [[0., 0., 0.], [0., 0., 0.]]),
       ([0, 0, 0], 0., [[0., 0., 0.], [0., 0., 0.]]),
       ([0, 0, 0], 0., [[0., 0., 0.], [0., 0., 0.]])],
      dtype=[('f0', 'i1', (3,)), ('f1', '<f4'), ('f2', '<f8', (2, 3))])

元祖参数对象

适用于记录结构的惟一相关元组是当结构映射到现有数据类型时。这是经过在元组中配对现有数据类型与匹配的dtype定义(使用此处描述的任何变体)来完成的。

x = np.zeros(3, dtype=('i4',[('r','u1'), ('g','u1'), ('b','u1'), ('a','u1')]))
x
Out[258]: 
array([0, 0, 0],
      dtype=(numpy.int32, [('r', 'u1'), ('g', 'u1'), ('b', 'u1'), ('a', 'u1')]))
x['r']
Out[259]: array([0, 0, 0], dtype=uint8)

列表参数

在这种状况下,记录结构用元组列表定义。每一个元组具备2或3个元素,指定:字段的名称(容许使用''),字段的类型,以及形状(可选)。

x = np.zeros(3, dtype=[('x','f4'),('y',np.float32),('value','f4',(2,2))])
x
Out[261]: 
array([(0., 0., [[0., 0.], [0., 0.]]), (0., 0., [[0., 0.], [0., 0.]]),
       (0., 0., [[0., 0.], [0., 0.]])],
      dtype=[('x', '<f4'), ('y', '<f4'), ('value', '<f4', (2, 2))])

字典参数

容许两种不一样的形式。第一个包含一个具备两个必需键('names'和'formats')的字典,每一个键都有一个相等大小的值列表。格式列表包含在其余上下文中容许的任何类型/形状说明符。名称必须是字符串。有两个可选键:“offsets”和“titles”。每一个都必须是相应匹配的列表,其中偏移量包含每一个字段的整数偏移量,标题是包含每一个字段的元数据的对象(这些对象没必要是字符串),其中容许值为None。举个例子:

x = np.zeros(3, dtype={'names':['col1', 'col2'], 'formats':['i4','f4']})
x
Out[263]: 
array([(0, 0.), (0, 0.), (0, 0.)],
      dtype=[('col1', '<i4'), ('col2', '<f4')])

容许的其余字典形式是具备指定类型,偏移和可选标题的元组值的名称键的字典。

x = np.zeros(3, dtype={'col1':('i1',0,'title 1'), 'col2':('f4',1,'title 2')})
x
Out[265]: 
array([(0, 0.), (0, 0.), (0, 0.)],
      dtype=[(('title 1', 'col1'), 'i1'), (('title 2', 'col2'), '<f4')])

访问字段标题

字段标题提供了一个标准位置来放置字段的关联信息。他们没必要是字符串。

x.dtype.fields['col1'][2]
Out[267]: 'title 1'

访问和修改字段名称

x.dtype.names
Out[268]: ('col1', 'col2')
x.dtype.names = ('x', 'y')
x
Out[270]: 
array([(0, 0.), (0, 0.), (0, 0.)],
      dtype=[(('title 1', 'x'), 'i1'), (('title 2', 'y'), '<f4')])

一次访问多个字段

您可使用字段名称列表一次访问多个字段:

x = np.array([(1.5, 2.5, (1.0, 2.0)), (3., 4., (4., 5.)), (1., 3., (2., 6.))],
             dtype=[('x', 'f4'), ('y', np.float32), ('value', 'f4', (2, 2))])

请注意,x是使用元组列表建立的。

x[['x','y']]
Out[272]: 
array([(1.5, 2.5), (3. , 4. ), (1. , 3. )],
      dtype=[('x', '<f4'), ('y', '<f4')])
x[['x','value']]
Out[273]: 
array([(1.5, [[1., 2.], [1., 2.]]), (3. , [[4., 5.], [4., 5.]]),
       (1. , [[2., 6.], [2., 6.]])],
      dtype=[('x', '<f4'), ('value', '<f4', (2, 2))])
x[x['y'] == 4]
Out[274]: 
array([(3., 4., [[4., 5.], [4., 5.]])],
      dtype=[('x', '<f4'), ('y', '<f4'), ('value', '<f4', (2, 2))])

字段按请求的顺序返回(能够用来调整数组顺序

x[['y','x']]
Out[275]: 
array([(2.5, 1.5), (4. , 3. ), (3. , 1. )],
      dtype=[('y', '<f4'), ('x', '<f4')])

    记录数组

虽然结构化数组已经可以经过字段索引来操做数组了,记录数组容许经过Python中属性的方式(就是以“.”的方式)来操做。

记录数组也使用特殊的数据类型numpy.record

建立记录数组的最简单的方法是使用numpy.rec.array

recordarr = np.rec.array([(1,2.,'Hello'),(2,3.,"World")], dtype=[('foo', 'i4'),('bar', 'f4'), ('baz', 'S10')])
recordarr.bar
Out[277]: array([2., 3.], dtype=float32)
recordarr[1:2]
Out[278]: 
rec.array([(2, 3., b'World')],
          dtype=[('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')])
recordarr[1:2].foo
Out[279]: array([2])
recordarr.foo[1:2]
Out[280]: array([2])
recordarr[1].baz
Out[281]: b'World'

numpy.rec.array能够将各类参数转换为记录数组,包括正常的结构化数组:

arr = np.array([(1,2.,'Hello'),(2,3.,"World")], dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
recordarr = np.rec.array(arr)
recordarr
Out[285]: 
rec.array([(1, 2., b'Hello'), (2, 3., b'World')],
          dtype=[('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')])
相关文章
相关标签/搜索