05-python-Structured-arrays

5. NumPy之:结构化数组详解

简介

普通的数组就是数组中存放了同一类型的对象。而结构化数组是指数组中存放不同对象的格式。

今天我们来详细探讨一下NumPy中的结构化数组。

结构化数组中的字段field

因为结构化数组中包含了不同类型的对象,所以每一个对象类型都被称为一个field。

每个field都有3部分,分别是:string类型的name,任何有效dtype类型的type,还有一个可选的title

看一个使用filed构建dtype的例子:

In [165]: np.dtype([('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
Out[165]: dtype([('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

我们可以使用上面的dtype类型来构建一个新的数组:

In [166]: x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
     ...:     dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
     ...:

In [167]: x
Out[167]:
array([('Rex', 9, 81.), ('Fido', 3, 27.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

x是一个1维数组,每个元素都包含三个字段,name,age和weight。并且分别指定了他们的数据类型。

可以通过index来访问一行数据:

也可以通过name来访问一列数据 :

还可以给所有的列统一赋值:

结构化数据类型

上面的例子让我们对结构化数据类型有了一个基本的认识。结构化数据类型就是一系列的filed的集合。

创建结构化数据类型

结构化数据类型是从基础类型创建的,主要有下面几种方式:

从元组创建

每个元组都是(fieldname, datatype, shape)这样的格式,其中shape 是可选的。fieldname 是 field的title。

如果fieldname是空字符的话,会以f开头的形式默认创建。

从逗号分割的dtype创建

可以选择从逗号分割的dtype类型创建:

从字典创建

从字典创建是这样的格式: {'names': ..., 'formats': ..., 'offsets': ..., 'titles': ..., 'itemsize': ...}

这种写法可以指定name列表和formats列表。

offsets 指的是每个字段的byte offsets。titles 是字段的title,itemsize 是整个dtype的size。

操作结构化数据类型

可以通过dtype 的 names 和fields 字段来访问结构化数据类型的属性:

Offsets 和Alignment

对于结构化类型来说,因为一个dtype中包含了多种数据类型,默认情况下这些数据类型是不对齐的。

我们可以通过下面的例子来看一下各个类型的偏移量:

如果在创建dtype类型的时候,指定了align=True,那么这些类型之间可能会按照C-struct的结构进行对齐。

对齐的好处就是可以提升处理效率。我们看一个对齐的例子:

Field Titles

每个Filed除了name之外,还可以包含title。

有两种方式来指定title,第一种方式:

第二种方式:

看一下fields的结构:

结构化数组

从结构化数据类型创建结构化数组之后,我们就可以对结构化数组进行操作了。

赋值

我们可以从元组中对结构化数组进行赋值:

还可以从标量对结构化数组进行赋值:

结构化数组还可以赋值给非机构化数组,但是前提是结构化数组只有一个filed:

结构化数组还可以互相赋值:

访问结构化数组

之前讲到了,可以通过filed的名字来访问和修改一列数据:

返回的数值是原始数组的一个视图,他们是共享内存空间的,所以修改视图同时也会修改原数据。

看一个filed是多维数组的情况:

上面构建了一个2 * 2 的矩阵,这个矩阵中的第一列是int类型,第二列是一个3 * 3 的float矩阵。

我们可以这样来查看各个列的shape值:

除了单列的访问之外,我们还可以一次访问多列数据:

多列同时赋值:

简单的交换列的数据:

Record Arrays

结构化数组只能通过index来访问,很不方便,为此NumPy提供了一个多维数组的子类 numpy.recarray, 然后可以通过属性来访问。

我们来看几个例子:

recarray返回的结果是一个rec.array。除了使用np.rec.array来创建之外,还可以使用view:

如果是rec.array对象,它的dtype类型会被自动转换成为np.record类型:

想要转换回原始的np.ndarray类型可以这样:

如果通过index或者field来访问rec.array对象的字段,如果字段是结构类型,那么会返回numpy.recarray,如果是非结构类型,则会返回numpy.ndarray:

本文已收录于 www.flydean.com

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

最后更新于

这有帮助吗?