二快速上手数组计算模块 Numpy
Posted Amo Xiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二快速上手数组计算模块 Numpy相关的知识,希望对你有一定的参考价值。
目录
NumPy 是数据分析的三大剑客之一,主要用于数组计算、矩阵运算和科学计算。对于刚开始学习数据分析的读者,建议灵活选择,重点掌握数组创建、数组的简单操作和计算即可。(不要死磕、钻牛角尖,先上手会使用,后续再深入理解)。为了便于理解,本文运用了大量的示意图,示例简单,力求使读者能够轻松地融入到 NumPy 的学习当中去。通过典型案例,让您充分理解 NumPy,应用 NumPy。下面让我们揭开 NumPy 的神秘面纱,开启 NumPy 之旅!本文学完之后,笔者还会提供相应的练习题给大家练习。
一、前置知识
二、初识 Numpy
2.1 NumPy 概述
官网:https://numpy.org/
文档:https://numpy.org/doc/stable/
中文教程:https://www.runoob.com/numpy/numpy-tutorial.html
NumPy 它是 Python 数组计算、矩阵运算和科学计算的核心库,NumPy 这个词来源于 Numerical 和 Python 两个单词的结合。NumPy 提供了一个高性能的数组对象,让我们轻松创建一维数组、二维数组和多维数组,以及大量的函数和方法,帮助我们轻松地进行数组计算,从而广泛地应用于数据分析、机器学习、图像处理和计算机图形学、数学任务等领域当中。NumPy 是数据分析的三大剑客之一,它的用途是以数组的形式对数据进行操作。机器学习中充斥了大量的数组运算,而 NumPy 使得这些操作变得简单。由于 NumPy 是通过 C 语言实现的,所以其运算速度非常快。具体功能如下:
- 有一个强大的N维数组对象 ndarray。
- 广播功能函数。(面试常问)
- 线性代数、傅立叶变换、随机数生成、图形操作等功能。
- 整合 C/C++/Fortran 代码的工具。
和我们小时候玩的魔方非常相似,如下:
安装 NumPy 模块: 在 一、Anaconda 介绍、安装及使用教程 一文中已经进行了演示,考虑到部分读者使用的集成开发环境为 Pycharm,故这里以 Pycharm 的方式进行演示,关于用 Anaconda 安装 NumPy 模块这里就不再进行赘述。打开 PyCharm,选择 File→Settings 菜单项,打开 Settings 窗口,然后在 Project Interpreter 窗口中选择添加模块的按钮 (+),如下图所示:
单击 (+) 按钮以后,在搜索栏输入需要添加的模块名称为 numpy,然后选择需要安装的模块,如下图所示,单击 Install Package 按钮即可安装 NumPy 模块。
也可以使用 pip 工具进行安装,安装命令如下:
pip install 包名称
pip install -i http://pypi.douban.com/simple --trusted-host pypi.douban.com numpy
测试是否安装成功,如下:
重要:建议大家还是和我环境保持一致,都使用 Anaconda!!!
在前文中,我们多次提到数组的概念。那在正式学习 Numpy 之前,我们先了解一下数组的相关概念。数组可分为一维数组、二维数组、三维数组,其中三维数组是常见的多维数组,如下图所示:
一维数组。 一维数组很简单,基本和 Python 列表一样,区别在于数组切片针对的是原始数组(这就意味着,如果对数组进行修改,原始数组也会跟着更改)。二维数组。 二维数组的本质是以数组作为数组元素。二维数组包括行和列,类似于表格形状,又称为矩阵。三维数组。 三维数组是指维数为三的数组结构,也称矩阵列表。三维数组是最常见的多维数组,由于其可以用来描述三维空间中的位置或状态而被广泛使用。轴的概念。 轴是 NumPy 模块里的 axis,指定某个 axis,就是沿着这个 axis 做相关操作,其中二维数组的两个 axis 的指向如下图所示:
对于一维数组,情况有点特殊,它不像二维数组从上向下地操作,而是水平的,因此一维数组其 axis=0 的指向如下图所示:
2.2 创建数组
1、创建简单的数组。 NumPy 创建简单的数组主要使用 array 函数,语法如下:
Docstring:
array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0,
like=None)
Create an array.
参数说明:
- object: 任何具有数组接口方法的对象。
- dtype: 数据类型。
- copy: 布尔型,可选参数,默认值为 True,则 object 对象被复制;否则,只有当 __array__ 方法返回副本,object 参数为嵌套序列,或者需要副本满足数据类型和顺序要求时,才会生成副本。
- order: 元素在内存中的出现顺序,值为 K、A、C、F。如果 object 参数不是数组,则新创建的数组将按行排列 C,如果值为 F,则按列排列;如果 object 参数是一个数组,则以下内容成立:C(按行)、F(按列)、A(原顺序)、K(元素在内存中的出现顺序)。
- subok: 布尔型。如果值为 True,则将传递子类,否则返回的数组将强制为基类数组(默认值)。
- ndmin: 指定生成数组的最小维数。
示例1:演示如何创建数组。
import numpy as np # 导入numpy模块
# 1.创建一个简单的一维数组
n1 = np.array([1, 2, 3, 4])
# 2.创建一个包含小数的一维数组
n2 = np.array([0.1, 0.2, 0.3, 0.4])
# 3.创建一个简单的二维数组
n3 = np.array([[1,2], [3,4]])
# 查看创建的数组
print(n1)
n1, n2, n3
示例2:为数组指定数据类型。NumPy 支持比 Python 更多种类的数据类型,通过 dtype 参数可以指定数组的数据类型,程序代码如下:
import numpy as np # 导入numpy模块
num_list = [4, 5, 6] # 列表
# 1.创建浮点型数组
n1 = np.array(num_list, dtype=np.float_)
# n1 = np.array(num_list, dtype=np.float)
# 打印
print(n1)
print(n1.dtype)
print(type(n1[0]))
示例3:复制数组。当运算和处理数组时,为了不影响到原数组,就需要对原数组进行复制,而对复制后的数组进行修改和删除等操作都不会影响到原数组。数组的复制可以通过 copy 参数实现,程序代码如下:
import numpy as np # 导入numpy模块
# 创建一维数组
n1 = np.array([4, 5, 6])
# 复制数组
n2 = np.array(n1, copy=True) # 写不写无所谓,默认值就是True
n2[0] = 3 # 修改数组中的第一个元素为3
n2[2] = 1 # 修改数组中的第三个元素为1
print(n1, n2) # 打印
n3 = np.array(n1)
n3[0] = 6 # 修改数组中的第一个元素为3
n3[2] = 4 # 修改数组中的第三个元素为1
print(n1, n3)
示例4:通过 ndmin 参数控制最小维数。数组可分为一维数组、二维数组和多维数组,通过 ndmin 参数可以控制数组的最小维数。无论给出的数据的维数是多少,ndmin 参数都会根据最小维数创建指定维数的数组。
import numpy as np
nd1 = [1,2,3]
nd2 = np.array(nd1, ndmin=3) # 三维数组
print(nd2) # [[[1 2 3]]]
2、不同方式创建数组。
示例5:创建指定维度和未初始化的数组。主要使用 empty 函数,程序代码如下:
import numpy as np # 导入numpy模块
n = np.empty([2, 3])
print(n)
示例6:创建指定维度(以0填充)的数组。主要使用 zeros 函数,程序代码如下:
import numpy as np # 导入numpy模块
n = np.zeros([4])
print(n)
示例7:建指定维度并以1填充的数组。主要使用 ones 函数,程序代码如下:
import numpy as np # 导入numpy模块
n = np.ones([2,4])
print(n)
示例8:创建以指定值填充的数组。主要使用 full 函数,程序代码如下:
import numpy as np # 导入numpy模块
n = np.full((3,3,3), 9)
print(n)
3、从数值范围创建数组。
通过 arange 函数创建数组。arange 函数同 Python 内置的 range 函数相似,区别在于返回值,arange 函数的返回值是数组,而 range 函数的返回值是列表。arange 函数的语法如下:
Docstring:
arange([start,] stop[, step,], dtype=None, *, like=None)
Return evenly spaced values within a given interval.
# 参数说明:
# 1. start:起始值,默认值为0。
# 2. stop:终止值(不包含)。
# 3. step:步长,默认值为1。
# 4. dtype:创建数组的数据类型,如果不设置数据类型,则使用输入数据的数据类型。
示例9:通过 arange 函数创建数组。使用 arange 函数时,主要通过数值范围创建数组,程序代码如下:
import numpy as np # 导入numpy模块
n1 = np.arange(3)
n2 = np.arange(3.0)
n3 = np.arange(3,7)
n4 =np.arange(3,15,2)
print(n1, n2, n3, n4)
使用 linspace 函数创建等差数列。 首先简单了解一下等差数列,等差数列是指如果一个数列从第2项起,每一项与它的前一项的差等于同一个常数,那么这个数列就叫作等差数列。例如,一般成年男鞋的各种尺码,如下图所示:
关于马拉松的赛前训练,一周每天的训练量(单位:m),如下图所示:
在 Python 中,创建等差数列可以使用 NumPy 的 linspace 函数,该函数用于创建一个一维的等差数列的数组,它与 arange 函数不同,arange 函数是从开始值到结束值的左闭右开区间(即包括开始值,但不包括结束值),第三个参数(如果存在)是步长;而 linespace 函数是从开始值到结束值的闭区间(可以通过参数 endpoint=False 设置,使结束值不是闭区间),并且第三个参数是值的个数。
注意:博文中经常会提到诸如左闭右开区间、左开右闭区间、闭区间等,这里简单介绍一下。左闭右开区间:是指包括起始值但不包括终止值的一个数值区间;:左开右闭区间:是指不包括起始值但包括终止值的一个数值区间;闭区间:是指既包括起始值又包括终止值的一个数值区间。
linspace 函数的语法如下:
Signature:
np.linspace(
start,
stop,
num=50,
endpoint=True,
retstep=False,
dtype=None,
axis=0,
)
Docstring:
Return evenly spaced numbers over a specified interval.
# 参数说明:
# 1. start:序列的起始值。
# 2. stop:序列的终止值,如果endpoint参数的值为True,则该值包含于数列中。#
# 3. num:要生成的等步长的样本数量,默认值为50。
# 4. endpoint:如果值为Ture,数列中包含stop参数的值;反之则不包含,默认值为True。
# 5. retstep:如果值为True,则生成的数组中会显示间距,反之则不显示。
# 6. dtype:数组的数据类型。
示例10:创建马拉松赛前训练的等差数列数组。程序代码如下:
import numpy as np # 导入numpy模块
n1 = np.linspace(7500, 10000, 6)
print(n1)
使用 logspace 函数创建等比数列。首先了解一下等比数列,等比数列是指从第二项起,每一项与它的前一项的比值等于同一个常数的一种数列。例如,在古印度,国王要重赏发明国际象棋的大臣,对他说:“我可以满足你的任何要求。”,大臣说:“请给我的棋盘的64个格子都放上小麦,第1个格子放1粒小麦,第2个格子放2粒小麦,第3个格子放4粒小麦,第4个格子放8粒小麦,如下图所示,后面每个格子放的小麦数都是前一个格子里放的2倍,直到第64个格子。”。
在 Python 中,创建等比数列可以使用 NumPy 的 logspace 函数,语法如下:
Signature:
np.logspace(
start,
stop,
num=50,
endpoint=True,
base=10.0,
dtype=None,
axis=0,
)
Docstring:
Return numbers spaced evenly on a log scale.
# 参数说明:
# 1. start:序列的起始值。
# 2. stop:序列的终止值。如果 endpoint 参数值为 True,则该值包含于数列中。
# 3. num:要生成的等步长的数据样本数量,默认值为50。
# 4. endpoint:如果值为Ture,则数列中包含 stop 参数值;反之则不包含,默认值为 True。
示例11:通过 logspace 函数解决棋盘放置小麦的问题。通过 logspace 函数计算棋盘中的每个格子里放的小麦数是前一个格子里的2倍,直到第64个格子时,每个格子里会放多少小麦,程序代码如下:
import numpy as np # 导入numpy模块
n = np.logspace(0, 63, 64, base=2, dtype='int')
print(n)
程序运行结果如下图所示:
注意上述举例,出现一个问题:后面大数出现负数,而且都是一样的,这是由于程序中指定的数据类型是int,是32位的,数据范围为 -2147483648~2147483647,而我们计算后的数据远远超出了这个范围,便出现了溢出现象。解决这一问题,需要指定数据类型为 uint64(即无符号整数,数据范围为 0~18446744073709551615),关键代码如下:
n = np.logspace(0, 63, 64, base=2, dtype='uint64')
运行程序,输出结果如下图所示:
以上就是每一个格子里需要放的小麦数,可见发明国际象棋的大臣是多么聪明。说明:关于 NumPy 数据类型的详细介绍将在博文后面展开。
4、生成随机数组。 随机数组的生成主要使用 NumPy 中的 random 模块,下面介绍几种常用的随机生成数组的函数。
rand 函数。rand 函数用于生成 (0,1) 之间的随机数组,传入一个值随机生成一维数组,传入一对值随机生成二维数组,语法如下:
Docstring:
rand(d0, d1, ..., dn)
Random values in a given shape.
# 参数 d0、d1…dn 为整数,表示维度,可以为空。
示例12:随机生成0到1之间的数组。程序代码如下:
说明:此处笔者得到的结果会与读者朋友的不同,属于正常情况。
randn 函数。randn 函数用于从正态分布中返回随机生成的数组,语法如下:
Docstring:
randn(d0, d1, ..., dn)
Return a sample (or samples) from the "standard normal" distribution.
# 参数d0、d1…dn为整数,表示维度,可以为空。
补充:什么是正态分布?正态分布 (Normal distribution),也称“常态分布”,又名高斯分布 (Gaussian distribution),最早由棣莫弗(Abraham de Moivre) 在求二项分布的渐近公式中得到。C.F.高斯在研究测量误差时从另一个角度导出了它。P.S.拉普拉斯和高斯研究了它的性质。是一个在数学、物理及工程等领域都非常重要的概率分布,在统计学的许多方面有着重大的影响力。正态曲线呈钟型,两头低,中间高,左右对称因其曲线呈钟形,因此人们又经常称之为钟形曲线。若随机变量 X 服从一个数学期望为 μ、方差为 σ2 的正态分布,记为 N(μ,σ2)。其概率密度函数为正态分布的期望值 μ 决定了其位置,其标准差 σ 决定了分布的幅度。当 μ = 0,σ = 1 时的正态分布是标准正态分布。如下图所示:
示例13:随机生成满足正态分布的数组。程序代码如下:
import numpy as np
n1 = np.random.randn(5)
print('随机生成满足正态分布的一维数组:')
print(n1)
n2 = np.random.randn(2,5)
print('随机生成满足正态分布的二维数组:')
print(n2)
randint 函数。randint 函数与 NumPy 中的 arange 函数类似。randint 函数用于生成一定范围内的随机数组,左闭右开区间,语法如下:
Docstring:
randint(low, high=None, size=None, dtype=int)
Return random integers from `low` (inclusive) to `high` (exclusive).
# 参数说明:
# 1.low:低值(起始值),整数,且当参数high不为空时,参数low应小于参数high,否则程序会出现错误。
# 2.high:高值(终止值),整数。
# 3.size:数组维数,整数或者元组,整数表示一维数组,元组表示多维数组。默认值为空,如果为空,则仅返回一个整数。
示例14:生成一定范围内的随机数组。程序代码如下:
import numpy as np
n1 = np.random.randint(1, 3, 10)
print('随机生成10个1到3之间且不包括3的整数:')
print(n1)
n2 = np.random.randint(5,10)
print('size数组大小为空随机返回一个整数:')
print(n2)
n3 = np.random.randint(5,size=(2,5))
print('随机生成5以内二维数组')
print(n3)
normal 函数。normal 函数用于生成正态分布的随机数,语法如下:
Docstring:
normal(loc=0.0, scale=1.0, size=None)
Draw random samples from a normal (Gaussian) distribution.
# 参数说明:
# 1.loc:正态分布的均值,对应正态分布的中心。'loc=0'说明是一个以y轴为对称轴的正态分布。
# 2.scale:正态分布的标准差,对应正态分布的宽度,scale值越大,正态分布的曲线越矮胖;scale值越小,曲线越高瘦。
# 3.size:表示数组维数。
示例15:生成正态分布的随机数组。程序代码如下:
import numpy as np
n = np.random.normal(3, 2.5, size=(2, 4))
print(n)
5、从已有的数组中创建数组。
asarray 函数。asarray 函数用于创建数组,其与 array 函数类似,语法如下:
Docstring:
asarray(a, dtype=None, order=None, *, like=None)
Convert the input to an array.
# 参数说明:
# 1.a:可以是列表、列表的元组、元组、元组的元组、元组的列表或多维数组。
# 2.dtype:数组的数据类型。
# 3.order:值为"C"和"F",分别代表按行排列和按列排列,即数组元素在内存中的出现顺序。
示例16:使用 asarray 函数创建数组。程序代码如下:
import numpy as np # 导入numpy模块
n1 = np.asarray([1, 2, 3]) # 通过列表创建数组
n2 = np.asarray([(1, 1),(1, 2)]) # 通过列表的元组创建数组
n3 = np.asarray((1, 2, 3)) # 通过元组创建数组
n4 = np.asarray(((1, 1),(1, 2),(1, 3))) # 通过元组的元组创建数组
n5 = np.asarray(([1, 1],[1, 2])) # 通过元组的列表创建数组
print(n1)
print(n2)
print(n3)
print(n4)
print(n5)
frombuffer 函数。NumPy 中的 ndarray 数组对象不能像 Python 列表一样动态地改变其大小,因为在做数据采集时很不方便。下面介绍如何通过 frombuffer 函数实现动态数组。frombuffer 函数接受 buffer 输入参数,以流的形式将读入的数据转换为数组。frombuffer 函数的语法如下:
Docstring:
frombuffer(buffer, dtype=float, count=-1, offset=0, *, like=None)
Interpret a buffer as a 1-dimensional array.
# 参数说明:
# 1.buffer:实现了__buffer__方法的对象。
# 2.dtype:数组的数据类型。
# 3.count:读取的数据数量,默认值为-1,表示读取所有数据。
# 4.offset:读取的起始位置,默认值为0。
示例17:将字符串 AmoXiang 转换为数组。程序代码如下:
import numpy as np
import array
n = np.frombuffer(b'AmoXiang',dtype='S1')
print(n)
a = array.array("i", [1, 2, 3, 4])
na = np.frombuffer(a, dtype=int)
print(na)
a.append(5)
print(na)
注意:当 buffer 参数值为字符串时,Python 3 版本默认字符串是 Unicode 类型,所以要转换成 Byte string 类型,需要在原字符串前加上 b。
fromiter 函数 。fromiter 函数用于从可迭代对象中建立数组对象,语法如下:
Docstring:
fromiter(iter, dtype, count=-1, *, like=None)
Create a new 1-dimensional array from an iterable object.
# 参数说明:
# 1.iterable:可迭代对象。
# 2.dtype:数组的数据类型。
# 3.count:读取的数据数量,默认值为-1,表示读取所有数据。
示例18:通过可迭代对象创建数组。程序代码如下:
import numpy as np
iterable = (x * 2 for x in range(5)) # 遍历0~5并乘以2,返回可迭代对象
n = np.fromiter(iterable, dtype='int') # 通过可迭代对象创建数组
print(n)