“五色令人目盲,五音令人耳聋,五味令人口爽,驰骋畋猎令人心发狂,难得之货令人行妨。
是以圣人为腹不为目,故去彼取此。”1
numpy
NumPy数组通常是由相同种类的元素组成的,既数组中的数据项的类型必须一致。
通常先要引入numpy包:
1 | import numpy as np |
创建一个简单的一维数据:
1 | arr1 = np.arange(5) |
2 | arr1 |
输出:
1 | dtype('int64') |
以上数组的数据类型为int64,除了知道数据类型之外,还要注意其形状,这一点非常重要。
1 | arr1 |
输出:
1 | array([0, 1, 2, 3, 4]) |
1 | arr1.shape |
输出:
1 | (5,) |
如你所见,该向量有5个元素,他们的值分别是从0到4,该数组的shape属性是一个元组,存放的是数组在每一个维度的长度。
创建多维数据
数组大于一维以后,我们习惯称之为矩阵,下面创建一个2行2列的矩阵:
1 | metr = np.array([1,2],[3,4]) |
上面的矩阵是通过向array()函数传递一个由列表组成的列表得到的,接下来,我们要逐个选择矩阵的各个元素,代码如下所示。下标从0开始,如下取出第1行第1列、第2行第2列的元素:
1 | metr[0][0] |
2 | metr[1][1] |
输出:
1 | 1 |
2 | 4 |
可见,选择数组元素是一件非常简单的事情,对于数组metr,只要通过metr[m,n]的形态,就能访问数组内的元素,其中m和n为数组元素的下标。
一维数组的切片与索引
一维NumPy数组的切片操作与Python列表的切片一样。下面先来定义包括0、1、2,直到8的一个数组,然后通过指定下标2到5来选择该数组的部分元素,这实际上就是提取数组中值为2到5的那些元素。
1 | arr2 = np.arange(9) |
2 | arr2[2:6] |
输出:
1 | array([2, 3, 4, 5]) |
可以用下标选择元素,下标范围从0到7,并且下标每次递增2,如:
1 | arr2[:7:2] |
输出:
1 | array([0, 2, 4, 6]) |
恰如使用Python那样,也可用负值下标来反转数组:
1 | arr2[::-1] |
输出:
1 | array([8, 7, 6, 5, 4, 3, 2, 1, 0]) |
处理数组形态
常用的处理数组形态的方法,先记录如下几个:
- reshape()
- ravel()
- flatten()
- transpose()
- resize()
reshape()
将一个由0到11构成的一维数组,改变为3行4列的二维数组:输出:1arr3 = np.arange(12).reshape(3,4)2arr31array([[ 0, 1, 2, 3],2[ 4, 5, 6, 7],3[ 8, 9, 10, 11]])ravel()
将多维数组变成一维数组
将上面的二维数据再改变为一维数组:输出:1arr3.ravel()1array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])flatten()
其功能与ravel()相同。可是,flatten()返回的是真实的数组,需要分配新的内存空间;而ravel()函数返回的只是数组的视图。两者的区别在于返回拷贝(copy)还是返回视图(view),numpy.flatten()返回一份拷贝,对拷贝所做的修改不会影响(reflects)原始矩阵,而numpy.ravel()返回的是视图(view,也颇有几分C/C++引用reference的意味),会影响(reflects)原始矩阵。输出:1arr3.flatten()1array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])transpose()
转置:在线性代数中,矩阵的转置操作非常常见。转置是一种数据变换方法,对于二维表而言,转置就意味着行变成列,同时列变成行。
如:创建一个0-11数字组成的一维数组,先reshape为3行4列的数组:输出:1arr4 = np.arange(12).reshape(3,4)2arr4然后对其进行转置:1array([[ 0, 1, 2, 3],2[ 4, 5, 6, 7],3[ 8, 9, 10, 11]])输出:1arr4.transpose()1array([[ 0, 4, 8],2[ 1, 5, 9],3[ 2, 6, 10],4[ 3, 7, 11]])resize()
调整大小:函数resize()的作用类似于reshape(),但是会改变所作用的数组:
如:将arr4调整为2行6列的二维数组输出:1arr4.resize(2,6)2arr41array([[ 0, 1, 2, 3, 4, 5],2[ 6, 7, 8, 9, 10, 11]])堆叠数组
从深度看,数组既可以横向叠放,也可以竖向叠放。涉及许下几个方法: - vstack()
- dstack()
- hstack()
- column_stack()
- row_stack()
- concatenate()
先创建两个数组a 和 b,均为3行3列的二维数据:
数组a
1 | a = np.arange(9).reshape(3,3) |
2 | a |
输出a:
1 | array([[0, 1, 2], |
2 | [3, 4, 5], |
3 | [6, 7, 8]]) |
数组b
1 | b = a*2 |
2 | b |
输出b:
1 | array([[ 0, 2, 4], |
2 | [ 6, 8, 10], |
3 | [12, 14, 16]]) |
hstack()
水平叠加:先介绍水平叠加方式,即用元组确定ndarrays数组的形状,然后交由hstack()函数来码放这些数组。
1 | np.hstack((a,b)) |
输出:
1 | array([[ 0, 1, 2, 0, 2, 4], |
2 | [ 3, 4, 5, 6, 8, 10], |
3 | [ 6, 7, 8, 12, 14, 16]]) |
将调用hstack时a和b的入参顺序换一下再看看结果:
1 | np.hstack((b,a)) |
输出:
1 | array([[ 0, 2, 4, 0, 1, 2], |
2 | [ 6, 8, 10, 3, 4, 5], |
3 | [12, 14, 16, 6, 7, 8]]) |
vstack()
垂直叠加:使用垂直叠加方法时,先要构建一个元祖,然后将元祖交给vstack()函数来码放数组。
1 | np.vstack((a,b)) |
输出:
1 | array([[ 0, 1, 2], |
2 | [ 3, 4, 5], |
3 | [ 6, 7, 8], |
4 | [ 0, 2, 4], |
5 | [ 6, 8, 10], |
6 | [12, 14, 16]]) |
当参数axis置0时,concatenate()函数也会得到相同的效果。实际上,这是该参数的缺省值:
1 | np.concatenate((a,b),axis=0) |
输出:
1 | array([[ 0, 1, 2], |
2 | [ 3, 4, 5], |
3 | [ 6, 7, 8], |
4 | [ 0, 2, 4], |
5 | [ 6, 8, 10], |
6 | [12, 14, 16]]) |
dstack()
深度叠加:除此之外,还有一种深度叠加方法,这要用到dstack()函数和一个元组。这种方法是沿着第三个坐标轴(纵向)的方向来叠加一摞数组。举例来说,可以在一个图像数据的二维数组上叠加另一幅图像的数据。
1 | np.dstack((a,b)) |
输出:
1 | array([[[ 0, 0], |
2 | [ 1, 2], |
3 | [ 2, 4]], |
4 | |
5 | [[ 3, 6], |
6 | [ 4, 8], |
7 | [ 5, 10]], |
8 | |
9 | [[ 6, 12], |
10 | [ 7, 14], |
11 | [ 8, 16]]]) |
####拆分numpy数组
可以从纵向,横向和深度方向来拆分数组,相关函数有hsplit(),vsplit(),dsplit()和split()。我们即可以把数组分成相同的形状的数组,也可以从规定的位置开始切取数组。
横向拆分:对于一个3行3列数组,可以沿着横轴方向将其分解为3部分,并且各部分的大小和形状完全一致。
1 | np.hsplit(a,3) |
输出:
1 | [array([[0], |
2 | [3], |
3 | [6]]), array([[1], |
4 | [4], |
5 | [7]]), array([[2], |
6 | [5], |
7 | [8]])] |
这个相当于调用了参数axis = 1的split()函数:
1 | np.split(a,3,1) |
输出:
1 | [array([[0], |
2 | [3], |
3 | [6]]), array([[1], |
4 | [4], |
5 | [7]]), array([[2], |
6 | [5], |
7 | [8]])] |
纵向拆分:同理
1 | np.vsplit(a,3) |
输出:
1 | [array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])] |
深向拆分:dsplit()函数会沿着深度方向分解数组。
后记:关于本文数据的由来
玩python,最好在本地安装Anaconda,里面有notebook的运行环境,交互式的笔记notebook是最好的工具,没有之一。
下载安装anaconda,运行,如下图为主界面

点击”jupyter notebook”,可以启动notebook运行环境,新建一个notebook python的文档,形如界面:

目前网上支持notebook最好的免费平台就是github了,将自己的notebook文档上传到github上可以进行分享。
1:老子《道德经》第十二章,老子故里,中国鹿邑。