《Python数据分析》一2.6 处理数组形状
本节书摘来自异步社区《Python数据分析》一书中的第2章,第2.6节,作者【印尼】Ivan Idris,更多章节内容可以访问云栖社区“异步社区”公众号查看
前面,我们学习过reshape()函数,实际上,除了数组形状的调整外,数组的扩充也是一个经常碰到的乏味工作。比如,可以想像一下将多维数组转换成一维数组时的情形。下面的代码就是用来干这件事情的,它取自本书代码包中的shapemanipulation.py文件:
import numpy as np # Demonstrates multi dimensional arrays slicing. # Run from the commandline with # python shapemanipulation.py print "In: b = arange(24).reshape(2,3,4)" b = np.arange(24).reshape(2,3,4) print "In: b" print b #Out: #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]]]) print "In: b.ravel()" print b.ravel() #Out: #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]) print "In: b.flatten()" print b.flatten() #Out: #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]) print "In: b.shape = (6,4)" b.shape = (6,4) print "In: b" print b #Out: #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]]) print "In: b.transpose()" print b.transpose() #Out: #array([[ 0, 4, 8, 12, 16, 20], # [ 1, 5, 9, 13, 17, 21], # [ 2, 6, 10, 14, 18, 22], # [ 3, 7, 11, 15, 19, 23]]) print "In: b.resize((2,12))" b.resize((2,12)) print "In: b" print b #Out: #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]]) 可以利用以下函数处理数组的形状。 拆解:可以用ravel()函数将多维数组变成一维数组,代码如下: In: b Out: 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]]]) In: b.ravel() Out: 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])
拉直(Flatten):flatten()函数的名字取得非常贴切,其功能与ravel()相同。可是,flatten()返回的是真实的数组,需要分配新的内存空间;而ravel()函数返回的只是数组的视图。这意味着,我们可以像下面这样直接操作数组:
In: b.flatten() Out: 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])
用元组指定数组形状:除reshape()函数外,还可以用元组来轻松定义数组的形状,如下所示:
In: b.shape = (6,4) In: b Out: 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]])
可见,上述代码直接改变了数组的形状。这样,我们就得到了一个6×4的数组。
转置:在线性代数中,矩阵的转置操作非常常见。转置是一种数据变换方法,对于二维表而言,转置就意味着行变成列,同时列变成行。转置也可以通过下列代码完成:
In: b.transpose() Out: array([[ 0, 4, 8, 12, 16, 20], [ 1, 5, 9, 13, 17, 21], [ 2, 6, 10, 14, 18, 22], [ 3, 7, 11, 15, 19, 23]])
调整大小:函数resize()的作用类似于reshape(),但是会改变所作用的数组:
In: b.resize((2,12)) In: b Out: 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]])2.6.1 堆叠数组
从深度看,数组既可以横向叠放,也可以竖向叠放。为此,可以使用vstack()、dstack()、hstack()、column_stack()、row_stack()和concatenate()等函数。在此之前,我们先要建立某些数组(以下代码取自本书代码包中的stacking.py文件):
In: a = arange(9).reshape(3,3) In: a array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) In: b = 2 * a In: b array([[ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])
就像前面所说的,可以用下列技术来堆放数组。
水平叠加:先介绍水平叠加方式,即用元组确定ndarrays数组的形状,然后交由hstack()函数来码放这些数组。具体如下所示:
In: hstack((a, b)) Out: array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8, 10], [ 6, 7, 8, 12, 14, 16]])
用concatenate()函数也能达到同样的效果,代码如下所示:
In: concatenate((a, b), axis=1) Out: array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8, 10], [ 6, 7, 8, 12, 14, 16]])
水平叠加过程的示意图如图2-1所示:
![fb2717141b49ce33713e8bf4fa30f442a6e41ea2](https://yqfile.alicdn.com/fb2717141b49ce33713e8bf4fa30f442a6e41ea2.png)
垂直叠加:使用垂直叠加方法时,先要构建一个元组,然后将元组交给vstack()函数来码放数组,代码如下所示:
In: vstack((a, b)) Out: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])
当参数axis置0时,concatenate()函数也会得到同样的效果。实际上,这是该参数的缺省值,代码如下所示:
In: concatenate((a, b), axis=0) Out: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]])
垂直叠加过程的示意图如图2-2所示。
![e49cbaecd9d6060ae6f5b5ba09f916980c26b737](https://yqfile.alicdn.com/e49cbaecd9d6060ae6f5b5ba09f916980c26b737.png)
深度叠加:除此之外,还有一种深度叠加方法,这要用到dstack()函数和一个元组。这种方法是沿着第三个坐标轴(纵向)的方向来叠加一摞数组。举例来说,可以在一个图像数据的二维数组上叠加另一幅图像的数据,代码如下所示:
In: dstack((a, b)) Out: array([[[ 0, 0], [ 1, 2], [ 2, 4]], [[ 3, 6], [ 4, 8], [ 5, 10]], [[ 6, 12], [ 7, 14], [ 8, 16]]])
列式堆叠:column_stack()函数以列方式对一维数组进行堆叠。代码如下所示:
In: oned = arange(2) In: oned Out: array([0, 1]) In: twice_oned = 2 * oned In: twice_oned Out: array([0, 2]) In: column_stack((oned, twice_oned)) Out: array([[0, 0], [1, 2]])
用这种方法堆叠二维数组时,过程类似于hstack()函数,代码如下所示:
In: column_stack((a, b)) Out: array([[ 0, 1, 2, 0, 2, 4], [ 3, 4, 5, 6, 8, 10], [ 6, 7, 8, 12, 14, 16]]) In: column_stack((a, b)) == hstack((a, b)) Out: array([[ True, True, True, True, True, True], [ True, True, True, True, True, True], [ True, True, True, True, True, True]], dtype=bool)
是的,你猜得没错!我们用==运算符对两个数组进行了比对。
行式堆叠:同时,NumPy自然也有以行方式对数组进行堆叠的函数,这个用于一维数组的函数名为row_stack(),它将数组作为行码放到二维数组中,代码如下所示:
In: row_stack((oned, twice_oned)) Out: array([[0, 1], [0, 2]])
对于二维数组,row_stack()函数相当于vstack()函数,如下所示:
In: row_stack((a, b)) Out: array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 0, 2, 4], [ 6, 8, 10], [12, 14, 16]]) In: row_stack((a,b)) == vstack((a, b)) Out: array([[ True, True, True], [ True, True, True], [ True, True, True], [ True, True, True], [ True, True, True], [ True, True, True]], dtype=bool)2.6.2 拆分NumPy数组
可以从纵向、横向和深度方向来拆分数组,相关函数有hsplit()、vsplit()、dsplit()和split()。我们既可以把数组分成相同形状的数组,也可以从规定的位置开始切取数组。下面对相关函数逐个详解。
横向拆分:对于一个3×3数组,可以沿着横轴方向将其分解为3部分,并且各部分的大小和形状完全一致,代码(它取自本书代码包中的splitting.py文件)如下所示:
In: a Out: array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) In: hsplit(a, 3) Out: [array([[0], [3], [6]]), array([[1], [4], [7]]), array([[2], [5], [8]])]
这相当于调用了参数axis=1的split()函数:
In: split(a, 3, axis=1) Out: [array([[0], [3], [6]]), array([[1], [4], [7]]), rray([[2], [5], [8]])]
纵向拆分:vsplit()函数将沿着纵轴方向分解数组。
In: vsplit(a, 3) Out: [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
当参数axis=0时,split()函数也会沿着纵轴方向分解数组,如下所示:
In: split(a, 3, axis=0) Out: [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])]
深向拆分:dsplit()函数会沿着深度方向分解数组。下面以秩为3的数组为例进行说明:
In: c = arange(27).reshape(3, 3, 3) In: c Out: 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]]]) In: dsplit(c, 3) Out: [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]]])]2.6.3 NumPy数组的属性
下面举例说明NumPy数组各种属性的详细用法。注意,下面的示例代码取自本书代码包中的arrayattributes2.py文件:
import numpy as np # Demonstrates ndarray attributes. # Run from the commandline with # python arrayattributes2.py b = np.arange(24).reshape(2, 12) print "In: b" print b #Out: #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]]) print "In: b.ndim" print b.ndim #Out: 2 print "In: b.size" print b.size #Out: 24 print "In: b.itemsize" print b.itemsize #Out: 8 print "In: b.nbytes" print b.nbytes #Out: 192 print "In: b.size * b.itemsize" print b.size * b.itemsize #Out: 192 print "In: b.resize(6,4)" print b.resize(6,4) print "In: b" print b #Out: #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]]) print "In: b.T" print b.T #Out: #array([[ 0, 4, 8, 12, 16, 20], # [ 1, 5, 9, 13, 17, 21], # [ 2, 6, 10, 14, 18, 22], # [ 3, 7, 11, 15, 19, 23]]) print "In: b.ndim" print b.ndim #Out: 1 print "In: b.T" print b.T #Out: array([0, 1, 2, 3, 4]) print "In: b = array([1.j + 1, 2.j + 3])" b = np.array([1.j + 1, 2.j + 3]) print "In: b" print b #Out: array([ 1.+1.j, 3.+2.j]) print "In: b.real" print b.real #Out: array([ 1., 3.]) print "In: b.imag" print b.imag #Out: array([ 1., 2.]) print "In: b.dtype" print b.dtype #Out: dtype(complex128) print "In: b.dtype.str" print b.dtype.str #Out: c16 print "In: b = arange(4).reshape(2,2)" b = np.arange(4).reshape(2,2) print "In: b" print b #Out: #array([[0, 1], # [2, 3]]) print "In: f = b.flat" f = b.flat print "In: f" print f #Out: numpy.flatiter object at 0x103013e00 print "In: for it in f: print it" for it in f: print it print "In: b.flat[2]" print b.flat[2] #Out: 2 print "In: b.flat[[1,3]]" print b.flat[[1,3]] #Out: array([1, 3]) print "In: b" print b #Out: #array([[7, 7], # [7, 7]]) print "In: b.flat[[1,3]] = 1" b.flat[[1,3]] = 1 print "In: b" print b #Out: #array([[7, 1], # [7, 1]])
除shape和dtype属性外,ndarray类型的属性还很多,下面逐一列出。
ndim属性存储的是维度的数量,下面举例说明:
In: b Out: 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]]) In: b.ndim Out: 2
size属性用来保存元素的数量,用法如下所示:
In: b.size Out: 24
itemsize属性可以返回数组中各个元素所占用的字节数,代码如下所示:
In: b.itemsize Out: 8
如果想知道存储整个数组所需的字节数量,可以求助于nbytes属性。这个属性的值正好是itemsize属性值和size属性值之积。
In: b.nbytes Out: 192 In: b.size * b.itemsize Out: 192
T属性的作用与transpose()函数相同,下面举例说明:
In: b.resize(6,4) In: b Out: 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]]) In: b.T Out: array([[ 0, 4, 8, 12, 16, 20], [ 1, 5, 9, 13, 17, 21], [ 2, 6, 10, 14, 18, 22], [ 3, 7, 11, 15, 19, 23]])
如果数组的秩(rank)小于2,那么所得只是一个数组的视图:
In: b.ndim Out: 1 In: b.T Out: array([0, 1, 2, 3, 4])
对于NumPy来说,复数用j表示,下面举例说明如何用复数生成一个数组:
In: b = array([1.j + 1, 2.j + 3]) In: b Out: array([ 1.+1.j, 3.+2.j])
real属性将返回数组的实部;当数组元素全为实数时,就返回数组本身,如下 所示:
In: b.real Out: array([ 1., 3.])
i``mag属性存放的是数组的虚部。
In: b.imag Out: array([ 1., 2.])
如果数组含有复数,那么它的数据类型将自动变为复数类型,如下所示:
In: b.dtype Out: dtype(complex128) In: b.dtype.str Out: c16
flat属性可返回一个numpy.flatiter对象,这是获得flatiter对象的唯一方法,但我们无法访问flatiter的构造函数。可以使用flat的迭代器来遍历数组,就像遍历“胖”数组那样,代码如下所示:
In: b = arange(4).reshape(2,2) In: b Out: array([[0, 1], [2, 3]]) In: f = b.flat In: f Out: numpy.flatiter object at 0x103013e00 In: for item in f: print item .....: 3
当然,取得flatiter对象的元素也不难,如下所示:
In: b.flat[2] Out: 2
此外,还可以请求多个元素,如下所示:
In: b.flat[[1,3]] Out: array([1, 3])
同时,还可以给flat属性赋值。不过,需要注意的是,这个值将会覆盖整个数组内所有元素的值,下面举例说明:
In: b.flat = 7 In: b Out: array([[7, 7], [7, 7]])
此外,还可以返回指定的元素,代码如下:
In: b.flat[[1,3]] = 1 In: b Out: array([[7, 1], [7, 1]])
图2-3是对ndarray各种属性的一个小结。
![1103b19a1702f79848e99d2bb53019f69b7ccf1c](https://yqfile.alicdn.com/1103b19a1702f79848e99d2bb53019f69b7ccf1c.png)
2.6.4 数组的转换
可以把NumPy数组转换成Python列表,使用tolist()函数(详见本书代码包中的arrayconversion.py文件)即可。下面简单解释一下:
转换成列表:
In: b Out: array([ 1.+1.j, 3.+2.j]) In: b.tolist() Out: [(1+1j), (3+2j)]
astype()函数可以把数组元素转换成指定类型,代码如下所示:
In: b Out: array([ 1.+1.j, 3.+2.j]) In: b.astype(int) /usr/local/bin/ipython:1: ComplexWarning: Casting complex values to real discards the imaginary part #!/usr/bin/python Out: array([1, 3]) In: b.astype(complex) Out: array([ 1.+1.j, 3.+2.j])
提示:
当complex类型转换成int类型时,虚部将被丢弃。另外,还需要将数据类型的名称以字符串的形式传递给astype()函数。
上述代码没有显示警告信息,因为这次使用的是正确的数据类型。
【python进阶】你还在使用for循环新建数组?生成器表达式帮你一行解决 在本文中,介绍了生成器与表达式的用法,帮助我们快速创建数组以及其他序列,解锁了python序列的新姿势。在后续的更新中,我将继续对元组的高级姿势和玩法进行介绍。
异步社区 异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
相关文章
- 【Python成长之路】python 基础篇 -- global/nonlocal关键字使用
- 你应该了解的python 垃圾回收机制
- python之simplejson,Python版的简单、 快速、 可扩展 JSON 编码器/解码器
- 一些Python中的二维数组的操作方法
- vscode Python环境
- 一些Python中的二维数组的操作方法
- 基于Python中numpy数组的合并实例讲解
- 华为OD机试 - 最大股票收益(Java & JS & Python)
- Python语言学习之打印输出那些事:python输出图表和各种吊炸天的字符串或图画、版权声明(如README.md)等之详细攻略
- python居然能语音控制电脑壁纸切换,只需60行代码
- Python 中拼音库 PyPinyin 的用法
- 【阶段二】Python数据分析NumPy工具使用03篇:数组的预处理、数组形状更改、数组转置与数组合并
- 【阶段二】Python数据分析NumPy工具使用01篇:NumPy工具介绍、NumPy工具安装与数组的创建
- Python学习99:HTTP协议简介
- python 找出数组重复的元素
- 【华为机试真题 Python实现】数组的转换
- 【华为机试真题 Python实现】素勾股数
- python数据分析-numpy数组操作
- Python数据分析与展示:ndarray多维数组的存储与读取-2
- python基础===一行 Python 代码实现并行(转)
- python基础===Python性能优化的20条建议
- 多版本Python共存时pip给指定版本的python安装package的方法
- 【Leetcode刷题Python】53. 最大子数组和
- Python-OpenCV图像处理-02-numpy数组操作
- Python可视化数据分析01、python环境搭建
- 【Python实战】 ---- python 自带的 venv 虚拟环境更新 pip 失败