前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Python进阶】你真的明白NumPy中的ndarray吗?

【Python进阶】你真的明白NumPy中的ndarray吗?

作者头像
用户1508658
发布2019-07-26 22:30:26
1.9K0
发布2019-07-26 22:30:26
举报
文章被收录于专栏:有三AI有三AI

欢迎来到专栏《Python进阶》。在这个专栏中,我们会讲述Python的各种进阶操作,包括Python对文件、数据的处理,Python各种好用的库如NumPy、Scipy、Matplotlib、Pandas的使用等等。我们的初心就是带大家更好的掌握Python这门语言,让它能为我所用。

今天是《Python进阶》专栏的第三期,在本期中,我们将主要介绍Numpy的一些进阶知识。

作者&编辑 | 汤兴旺

如果你想掌握Python,那么NumPy是你必须要精通的。NumPy实际上是Python语言的一个扩展程序库,支持高维数组与矩阵运算,提供了大量的数学函数库。

1 ndarray内存机制

我们知道NumPy最重要的一个特点是其N维数组对象ndarray。通常ndarray内部由以下内容组成。

数据指针:一个指向实际数据的指针;

数据类型(dtype):描述了数组中每个元素所占的字节数;

维度(shape):一个表示数组形状(各维度大小)的元组。

跨度(strides):一个表示从当前元素前进到下一个元素需要跨过的字节数。

我们通过下面的代码看下ndarray的内容:

import numpy as np

a = np.arange(1,25).reshape((2,2,2,3))

print(type(a))

print(a.shape)

print(a.dtype)

print(a.strides)

这里的shape是指每个维度元素的个数。这里的四维数组每个维度的元素个数分别为2、2、2和3。咦,这好像不对呀!2+2+2+3=9,这不等于24呀!难道我分析错了吗?

当然不是,我们首先将a输出来,结果如下:

这里最里面一层[ ]可以代表1个一维数组,里面有3个元素。加粗的红色一对[ ]代表二维数组,它里面有二个[ ],即二维数组中有2个一维数组。所以认为第三维度中元素个数为2;加粗的紫色一对[ ]代表三维数组,它里面有二个[ ],即三维数组中有2个二维数组。所以认为第二维度中元素个数为2。同理,第一维度中元素个数为2。

相信你现在应该明白了shape中的元组为啥是(2,2,2,3)了吧。

说完shape,我们再来看下dtype,它是指数组元素类型,注意,这里的数组元组就是指1,2,...,23,24这样的元素。另外数组中每个元素的类型都是相同的,在这个数组中,数组中每个元素类型都为int32。

最后我们再分析下跨度(strides)。它是指从当前元素前进到下一个元素需要跨过的字节数。

我们可以看出上面例子中的strides=(48,24,12,4)。那么这四个数是怎么来的呢?

我们在上面的四维数组中,dtype 为 int,而int 占 4个字节。而第四维度里面有3个元素,总字节数为12,所以从第四度跨到第三维度需要跨过的字节数为12;第三维度里面有2个元素(一维数组),每个一维数组的总字节数为12,所以从第三维度跨到第二维度需要跨过的字节数为24。同理,从第二维度跨到第一维度的字节数为48。

所以上面例子中的四维数组的跨度为(48,24,12,4),它在内存中的表示如下图所示:

从上图可以明显的看出从要想到达第三维度(轴2),必须跨过第四维度(轴3),需要跨过3个元素,字节数为12;要想到达第一维度(轴0),必须跨过第二、三、四维度,总共12个元素,字节数为12*4=48。

这也就是在NumPy 中数据存储的方式。它存储在一个均匀连续的内存块中,可以这么理解,NumPy 将多维数组在内部以一维数组的方式存储,我们只要知道了每个元素所占的字节数(dtype)以及每个维度中元素的个数(shape),就可以快速定位到任意维度的任意一个元素。

2 NumPy高维数组索引与转置

2.1 索引

当提到索引时,你可能觉得很简单,不就是通过索引获取某个元素吗?道理的确是这样的。但是在面对高维数组时,通过索引来获取某个元素还是比较麻烦的。

下面我们通过一个案例来分析下一个四维数组的索引。

如果我想取得上图中17这个元素,应该怎么办呢?

首先将这个四维数组用上图的轴的形式来表示。我们可以先把它看成四个块,其中第0轴和第1轴确定某个块的位置,第2轴和第3轴确定块中某个元素具体的位置。

图中的17在第3块,如下图的黄色部分,用0轴和1轴来表示的话,索引就是[1,0]。

现在块的位置确定了,接下来我们确定块中元素的位置。如下图所示:

17这个元素在上图中的索引为[1,1]。接下来我们只需要把确定块的索引[1,0]和确定块中元素的索引[]按照[第0轴,第1轴,第2轴,第3轴]这样的格式合并即可,在这个案例中,合并后17的索引为[1,0,1,1]。

当然,你可以用下面的代码确认下,我们的分析是否正确。

import numpy as np

a = np.arange(1,25).reshape((2,2,2,3))

print(a[1,0,1,1])

这个就是高维数组的索引,你已经明白了吗?

2.2 高维数组转置

高维数组的转置一直是学习NumPy的一个难点,尽管在NumPy中只需要调用numpy.transpose就可以完成转置操作,但是你真的能分析清楚为什么结果是这样的吗?尤其是高维数组。下面我们就举一个比较简单的例子来分析下。如下:

上图是原数组,我们经过下面的代码进行转置,会得到如下的结果:

import numpy as np a = np.arange(16).reshape((2,2,4))

b = a.transpose((1,0,2)) print(b)

转置后的结果:

相信你已经看出了具体的差别了,那就是轴的索引顺序的互换。因为在代码中我们要求0轴和1轴互换,因此转置后的结果实际上就是a[1,0]会变成原数组a[0,1];a[0,1]会变成原数组a[1,0]。如果用图表示,就如下图所示:

相信你已经明白了其中的原理了,接下来留一个思考题,如下:

请问,从左到右怎么转置才能得到!

总结

本期我们介绍了ndarray的内存机制及高维数组的索引和转置。NumPy的知识还有很多,上面介绍的只是NumPy中比较难理解的几个问题,若想更加系统的学习NumPy及知道上面思考题的分析过程和答案,请移步我们的知识星球!

下期预告:Python库Scipy的高级应用

转载文章请后台联系

侵权必究

往期精选

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有三AI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档