Numpy 修炼之道 (10)—— 结构化数组

推荐阅读时间:10min~12min 文章内容:Numpy的结构化数组

上一篇:Numpy 修炼之道 (9)—— 广播机制

简介

之前我们操作Numpy的数组时,都是通过索引来操作的。针对二维数组,使用索引可以完成对行、列的操作。但是这是非常不直观的。可以把二维数组想象成一个excel表格,如果表格没有列名,操作起来会非常麻烦,针对这种情况,Numpy提供了结构化数组用来操作每列数据。

之前我们操作Numpy的数组时,都是通过索引来操作的。针对二维数组,使用索引可以完成对行、列的操作。但是这是非常不直观的。可以把二维数组想象成一个excel表格,如果表格没有列名,操作起来会非常麻烦,针对这种情况,Numpy提供了结构化数组用来操作每列数据。

来看一个示例:

>>> x = np.array([('Bob', 18, 2000.0),('Tom', 23, 4000.0)],
... dtype=[('name', 'S10'), ('age', np.int_), ('incom', np.float_)])
>>> x
array([('Bob', 18,  2000.), ('Tom', 23,  4000.)],
      dtype=[('name', 'S10'), ('age', '<i4'), ('incom', '<f8')])
>>> x.shape
(2L,)
>>> row = x[0]
>>> row
('Bob', 18,  2000.)
>>> col = x['name']
>>> col
array(['Bob', 'Tom'],
      dtype='|S10')

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

需要注意的是,不管是row还是col,获取到的都是只是视图,所以更改结构化数组x时,对应的视图也会发生改变。

>>> x['name'] = ['Bob01', 'Tom01']
>>> x
array([('Bob01', 18,  2000.), ('Tom01', 23,  4000.)],
      dtype=[('name', 'S10'), ('age', '<i4'), ('incom', '<f8')])
>>> row
('Bob01', 18,  2000.)
>>> col
array(['Bob01', 'Tom01'],
      dtype='|S10')

构建结构化数组

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

字符串参数

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

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).
   一般也避免使用!

示例如下:

>>> x = np.zeros(3, dtype='3int8, float32, (2,3)float64')
>>> x
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
array([0, 0, 0])
>>> x['r']
array([0, 0, 0], dtype=uint8)

列表参数

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

>>> x = np.zeros(3, dtype=[('x','f4'),('y',np.float32),('value','f4',(2,2))])
>>> x
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, 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
array([(0, 0.0), (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
array([(0, 0.0), (0, 0.0), (0, 0.0)],
      dtype=[(('title 1', 'col1'), '|i1'), (('title 2', 'col2'), '>f4')])

访问字段标题

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

>>> x.dtype.fields['x'][2]
'title 1'

访问和修改字段名称

>>> x.dtype.names
('col1', 'col2')
>>>
>>> x.dtype.names = ('x', 'y')
>>> x
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']]
array([(1.5, 2.5), (3.0, 4.0), (1.0, 3.0)],
     dtype=[('x', '<f4'), ('y', '<f4')])
>>> x[['x','value']]
array([(1.5, [[1.0, 2.0], [1.0, 2.0]]), (3.0, [[4.0, 5.0], [4.0, 5.0]]),
      (1.0, [[2.0, 6.0], [2.0, 6.0]])],
     dtype=[('x', '<f4'), ('value', '<f4', (2, 2))])
>>> x[x['y'] == 4]
array([( 3., 4., [[ 4., 5.], [ 4., 5.]])],
     dtype=[('x', '<f4'), ('y', '<f4'), ('value', '<f4', (2, 2))])

字段按请求的顺序返回(可以用来调整数组顺序):

>>> x[['y','x']]
array([(2.5, 1.5), (4.0, 3.0), (3.0, 1.0)],
     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
array([ 2.,  3.], dtype=float32)
>>> recordarr[1:2]
rec.array([(2, 3.0, 'World')], 
      dtype=[('foo', '<i4'), ('bar', '<f4'), ('baz', 'S10')])
>>> recordarr[1:2].foo
array([2], dtype=int32)
>>> recordarr.foo[1:2]
array([2], dtype=int32)
>>> recordarr[1].baz
'World'

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

>>> arr = array([(1,2.,'Hello'),(2,3.,"World")], 
...             dtype=[('foo', 'i4'), ('bar', 'f4'), ('baz', 'S10')])
>>> recordarr = np.rec.array(arr)

作者:无邪,个人博客:脑洞大开,专注于机器学习研究。

原文发布于微信公众号 - 脑洞科技栈(naodong-open)

原文发表时间:2018-03-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器学习实践二三事

python基础----map和reduce

map和reduce Map简单来说就是:一个映射函数就是对一些独立元素组成的概念上的列表的每一个元素进行指定的操作 Reduce简单来说就是:对一个列表的...

21160
来自专栏Python小屋

Python 3.6.x字符串格式化方法小结

1 使用%符号进行格式 使用%符号进行字符串格式化的形式如下图所示,格式运算符%之前的部分为格式字符串,之后的部分为需要进行格式化的内容。 ? Python...

31660
来自专栏锦小年的博客

Python数据分析(3)-numpy中nd数组的创建

1、ndarray的内存结构 和其他的库一样,每个库都可能有自己独特的数据结构,例如OpenCV,numpy库的多维数组叫做ndarray( N dimensi...

23780
来自专栏赵俊的Java专栏

两数之和

22630
来自专栏猿人谷

size_type、size_t、differentce_type以及ptrdiff_t

目录(?)[-] size_type size_t different_type ptrdiff_t size_t是unsigned类型,用于指明数...

22870
来自专栏猿人谷

求子数组的最大和

分析:输入一个整形数组,数组里有正数也有负数,数组中一个或连续的多个正数,求所有子数组的和的最大值。 当我们加上一个正数时,和会增加;当我们加上一个负数时,和会...

203100
来自专栏C/C++基础

printf()详解之终极无惑

printf()是C语言标准库函数,用于将格式化后的字符串输出到标准输出。标准输出,即标准输出文件,对应终端的屏幕。printf()申明于头文件stdio.h。

44130
来自专栏CodeSheep的技术分享

Java编程思想学习录(连载之:一切都是对象)

17680
来自专栏专注研发

交换排序—冒泡排序(Bubble Sort)

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们...

13120
来自专栏blackheart的专栏

[程序设计语言]-[核心概念]-04:数据类型

0. 概述 为何高级语言需要类型系统这个概念?在汇编时代是没有完整的数据类型系统的,结构化编程引入了结构化的控制流、为结构化设计的子程序,随之这种结构化的代码所...

19860

扫码关注云+社区

领取腾讯云代金券