应对期末考试,对本学期《Python 数据分析与应用》课程学习的内容进行复习。


# 第二章、NumPy 数值计算基础

章节考点:

(1)Numpy 两大对象及特点

(2)Series (一维数组)组成

(3)Numpy 数组的属性

(4)Numpy 生成数组、矩阵的常用函数、矩阵转置

NumPy 提供了 [两种基本的对象]]{.red}:

ndarray(N-dimensional Array Object):存储单一数据类型的多维数组。

ufunc(Universal Function Object):能够对数组进行处理的函数。

[!IMPORTANT]

考点:Numpy 两大对象及特点

# 1.NumPy 数组对象 ndarray

# 1)数组属性

属性名称属性说明
ndim返回 int, 表示数组的维数
shape返回 tuple, 表示数组形状的阵列,对于 n 行 m 列的矩阵,形状为 (n,m)
size返回 int, 表示数组的元素总数,等于数组形状的乘积
dtype返回 data-type, 表示数组中元素的数据类型
itemsize返回 int, 表示数组的每个元素的大小(以字节为单位)

itemsize 解释:例如,一个元素类型为 float64 的数组的 itemsize 属性值为 8(float64 占用 64 个 bits, 每个字节长度为 8,所以 64/8,占用 8 个字节),一个元素类型为 complex32 的数组的 itemsize 属性值为 4,即 32/8

[!IMPORTANT]

考点:Numpy 数组的属性

# 2)数组创建

①array 函数

NumPy 提供的 array 函数可以创建一维或多维数组,其基本使用格式:

numpy.array(object, dtype=None, \*,copy=True,order='K', subok=False, ndmin=0, like=None)

array 函数主要参数及其说明如下表:

参数名称参数说明
object接收 array_like, 表示所需创建的数组对象,无默认值
dtype接收 data-type, 表示数组所需的数据类型,如果未给定,那么选择保存对象所需的最小类型,默认为 None
ndmin接收 int, 表示指定生成数组应该具有的最小维数,默认为 0

②arange 函数

arange 函数创建数组。arange 函数类似于 Python 自带的函数 range,通过指定开始值、终值和步长来创建一维数组,创建的数组不含终值。arange 函数的基本使用格式:

numpy.arange([start, ]stop, [step, ]dtype=None, \*, like=None)

arange 函数常用参数及其说明如下表:

参数名称参数说明
start接收 int 或实数,表示数组的开始值,生成的区间包括该值,默认为 0
stop接收 int 或实数,表示数组的终值,生成的区间不包括该值,无默认值
step接收 int 或实数,表示在数组中,值之间的间距,默认为 1
dtype接收数据类型,表示输出数组的类型,默认为 None

③linspace 函数

linspace 函数通过指定开始值、终值和元素个数来创建一维数组,默认设置包括终值,这一点需要和 arange 函数区分。linspace 函数的基本使用格式如下。

numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)

linspace 函数的常用参数及其说明如下表:

参数名称参数说明
start接受 array_like, 表示起始值,无默认值
stop接受 array_like, 表示结束值,无默认值
num接收 int,表示生成的样本数,默认为 50
dtype接收数据类型,表示输出数组的类型,默认为 None

④logspace 函数

logspace 函数和 linspace 函数类似,它创建的是等比数列。logspace 函数的基本使用格式如下:

numpy.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0)

在 logspace 函数的参数中,除了 base 参数和 linspace 函数的 retstep 参数不同之外,其余均相同

⑤NumPy 还提供了其他函数用于创建特殊数组,如 zeros、eye、diag 和 ones 函数等

  • zeros 函数:用于创建值全部为 0 的数组,即创建的数组值全部填充为 0。

  • eye 函数:用于生成主对角线上的元素为 1,其他的元素为 0 的数组,类似单位矩阵。

  • diag 函数:创建类似对角的数组,即除对角线外的其他元素都为 0,对角线上的元素可以是 0 或其他值。

  • ones 函数:用于创建元素全部为 1 的数组,即创建的数组元素全部填充为 1。

# 3)数组数据类型

NumPy 极大程度地扩充了原生 Python 的数据类型。

在 NumPy 中,所有数组的数据类型是同质的,即数组中的所有元素类型必须是一致的。

将元素类型保持一致可以更容易确定该数组所需要的存储空间。

  • np.bool

  • np.int 8\16\32\64

  • np.uint 8\16\32\64

  • np.float32/64

  • np.complex 64\128

  • np.str\ _

  • np.datatime 64

# 4)生成随机数

手动创建数组往往很难达到数量要求,NumPy 提供了强大的生成随机数的功能。

①random 函数

对于 NumPy,与随机数相关的函数都在 random 模块中,其中包括了可以生成服从多种概率分布随机数的函数。

random 函数是最常见的生成随机数的方法,random 函数的基本使用格式如下。

numpy.random.random(size=None)

参数 size 接收 int,表示返回的随机浮点数大小,默认为 None

②rand 函数

rand 函数可以生成服从均匀分布的随机数,其使用格式如下。

numpy.random.rand(d0, d1, ..., dn)

参数 d0, d1, ..., dn 接收 int,表示返回数组的维度必须是非负数。如果没有给出参数,那么返回单个 Python 浮点数,无默认值。

③randn 函数

randn 函数可以生成服从正态分布的随机数,randn 函数的使用格式和参数说明与 rand 函数相同。

④randint 函数

randint 函数可以生成给定上下限范围的随机数,其基本使用格式如下。

numpy.random.randint(low, high=None, size=None, dtype=int)

randint 函数的常用参数及其说明如下表

参数名称参数说明
low接收 int 或类似数组的整数。表示数组最小值。无默认值
high接收 int 或类似数组的整数。表示数组最大值。默认 None
size接收 int 或整数元组。表示输出形状。默认为 None
dtype接收数据类型。表示输出数组的类型。默认为 Int

random 模块中,其他常用于生成随机数的函数如下表

函数说明
seed确定随机数生成器的种子
permutation返回一个序列的随机排列或返回一个随机排列的范围
Shuffle对一个序列进行随机排序
binomial产生二项分布的随机数
normal产生正态(高斯)分布的随机数
beta产生 beta 分布的随机数
chisquare产生卡方分布的随机数
gamma产生 gamma 分布的随机数
uniform产生在 [0,1] 中均匀分布的随机数

# 5)索引访问数组

NumPy 通常以提供高效率的数组著称,这主要归功于索引的易用性。

①一维数组的索引

一维数组的方法很简单,与 Python 中的 list 的索引方法一致。

a [start​ : end: step] 正向反向都可

② 多维数组的索引

多维数组的每一个维度都有一个索引,各个维度的索引之间用逗号隔开。

多维数组同样也可以使用整数序列和布尔值索引进行访问。

a [start:end,start:end] 第一个冒号是行,第二个冒号是列,也可以单行单列罗列。

# 6)变换数组的形态

在 NumPy 中,常用reshape 函数改变数组的 “形状”,即改变数组的维度。reshape 函数的基本使用格式如下

numpy.reshape(a, newshape, order='C')

reshape 函数在改变原始数据的形状的同时不改变原始数据的值。如果指定的维度和数组的元素数目不吻合,那么函数将抛出异常。

reshape 函数的常用参数及其说明如下表

参数名称参数说明
a接收 array_like。表示需要变换形态的数组。无默认值
newshape接收 int 或 int 型元组。表示变化后的形状的维度。无默认值
order接收 str。表示将元素放入数组中的顺序,可选 C、F、A。默认为 C

在 NumPy 中,可以使用 ravel 函数完成数组展平工作。

flatten 函数也可以完成数组展平工作。与 ravel 函数的区别在于,flatten 函数可以选择横向或纵向展平。

# 7)数组的组合

除了可以改变数组 “形状” 外,NumPy 也可以对数组进行组合。组合主要有横向组合与纵向组合。使用hstack 函数、vstack 函数和 concatenate 函数可完成数组的组合。

  • 横向组合是将 ndarray 对象构成的元组作为参数,传给 hstack 函数。
  • 纵向组合同样是将 ndarray 对象构成的元组作为参数,传给 vstack 函数。
  • concatenate 函数也可以实现数组的横向组合和纵向组合,其中当参数 axis=1 时,数组按照横向组合,当参数 axis=0 时,数组按照纵向组合。

# 8)分割数组

除了对数组进行横向和纵向的组合之外,还可以对数组进行分割。NumPy 提供了hsplit、vsplit、dsplit 和 split 函数,可以将数组分割成相同大小的子数组,也可以指定原数组中需 要分割的位置。

  • hsplit 函数:可以对数组进行横向分割,以 ndarray 对象构成的元组作为参数。

  • vsplit 函数:可以对数组进行纵向分割,以 ndarray 对象构成的元组作为参数。

  • split 函数:同样可以实现数组分割。当参数 axis=1 时,可以对数组进行横向分割;当参数 axis=0 时,可以对数组进行纵向分割。

# 2.NumPy 矩阵

# 1)创建 Numpy 矩阵

在 NumPy 中,矩阵是 ndarray 的子类,且数组和矩阵有着重要的区别。

NumPy 提供了两个基本的对象,分别是N 维数组对象和通用函数对象,其他对象都是在它们之上构建的。

矩阵是继承自 NumPy 数组对象的二维数组对象。与数学概念中的矩阵一样,NumPy 中的矩阵也是二维的。

使用 mat、matrix 和 bmat 函数可创建矩阵。

当使用 mat 函数创建矩阵时,如果输入 matrix 或 ndarray 对象,那么不会创建相应副本。因此,调用 mat 函数和调用 matrix (data, copy=False) 函数等价。

在大多数情况下,用户会根据小的矩阵来创建大的矩阵,即将小矩阵组合成大矩阵。在 NumPy 中,可以使用 bmat 分块矩阵(block matrix)函数实现。

在 NumPy 中,矩阵计算是针对整个矩阵中的每个元素进行的。与使用 for 循环相比,其在运算速度上更快。

除了能够实现各类运算外,矩阵还有其特有的属性,如下表

属性名称属性说明
T返回自身的转置
H返回自身的共轭转置
I返回自身的逆矩阵
A返回自身数据的二维数组的一个视图(没有做任何的复制)

# 2)Numpy 矩阵的常用函数

①ufunc 函数

[!IMPORTANT]

考试内容:Numpy 创建矩阵、矩阵的常用函数

# 3.NumPy 数组对象 nfunc

常用的 ufunc 函数运算有四则运算、比较运算和逻辑运算等

  • 四则运算:ufunc 函数支持全部的四则运算,并且保留习惯的运算符,和数值运算的使用方式一样,但是需要注意的是,操作的对象是数组。数组间的四则运算表示对每个数组中的元素分别进行四则运算,因此进行四则运算的两个数组的形状必须相同。

  • 比较运算:在 ufunc 函数中也支持完整的比较运算:>、<、==、>=、<=、!=。比较运算返回的结果是一个布尔数组,其每个元素为数组对应元素的比较结果。

  • 逻辑运算:在 NumPy 逻辑运算中,numpy.all 函数表示逻辑 and,numpy.any 函数表示逻辑 or。

# 1)ufunc 函数的广播机制

广播(Broadcasting)是指不同形状的数组之间执行算术运算的方式。

当使用 ufunc 函数进行数组计算时,ufunc 函数会对两个数组的对应元素进行计算。

进行这种计算的前提是两个数组的 shape 一致。如果两个数组的 shape 不一致,那么 NumPy 会实行广播机制。

NumPy 中的广播机制并不容易理解,特别是在进行高维数组计算的时候。

为了更好地使用广播机制,需要遵循以下 4 个原则。

  1. 让所有的输入数组向其中 shape 最长的数组看齐,shape 中不足的部分通过在前面加 1 补齐。

  2. 输出数组的 shape 是输入数组 shape 的各个轴上的最大值。

  3. 如果输入数组的某个轴和输出数组的对应轴的长度相同或其长度为 1,那么这个数组能够用于计算,否则系统将会出错。

  4. 当输入数组的某个轴的长度为 1 时,沿着此轴运算时使用此轴上的第一组值。

# 4. 利用 NumPy 进行统计分析

# 1)读写文件

NumPy 的文件读写主要有两种形式

  1. 二进制的文件读 / 写
  2. 文件列表形式的数据读 / 写

NumPy 提供了若干函数,可以将结果保存到二进制或文本文件中。

除此之外,NumPy 还提供了许多从文件读取数据并将其转换为数组的方法。

save 函数以二进制的格式保存数据,load 函数从二进制的文件中读取数据,save 函数的语法格式如下

numpy.save(file, arr, allow_pickle=True, fix_imports=True)
  • 参数 file 接收 str,表示要保存的文件的名称,需要指定文件保存的路径,如果未设置,那么将会保存到默认路径下面。

  • 参数 arr 接收 array_like,表示需要保存的数组。

save 函数就是将数组 arr 保存至名称为 “file” 的文件中,其文件的扩展名.npy 是系统自动添加的。

如果将多个数组保存到一个文件中,那么可以使用 savez 函数,其文件的扩展名为.npz。

当需要读取二进制文件时,可以使用 load 函数,用文件名作为参数,存储时可以省略扩展名,但读取时不能省略扩展名。

在实际的数据分析任务中,更多地是使用文本格式的数据,如 TXT 或 CSV 格式,因此通常会使用 savetxt 函数、loadtxt 函数和 genfromtxt 函数执行对文本格式数据的读取任务。

savetxt 函数可将数组写到以某种分隔符隔开的文本文件中,其基本使用格式如下。

numpy.savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\\n', header='', footer='', comments='\# ', encoding=None)
  • 参数 fname 接收 str,表示文件名。

  • 参数 X 接收 array_like,表示数组数据。

  • 参数 delimiter 接收 str,表示数据分隔符。

loadtxt 函数执行的是相反的操作,即将文件加载到一个二维数组中,其基本使用格式如下。

numpy.loadtxt(fname, dtype=\<class 'float'\>, comments='\#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding='bytes', max_rows=None, \*, like=None)

loadtxt 函数的常用参数主要有两个,分别是 fname 和 delimiter。

  • 参数 fname 接收 str,表示需要读取的文件、文件名或生成器。

  • 参数 delimiter 接收 str,表示用于分隔数值的分隔符。

genfromtxt 函数和 loadtxt 函数相似,只不过 genfromtxt 函数面向的是结构化数组和缺失数据。

genfromtxt 函数通常使用的参数有 3 个。

  • 即用于存放数据的文件名参数 “fname”。

  • 用于分隔的字符参数 “delimiter”。

  • 是否含有列标题参数 “names”。

# 2)使用函数进行简单的统计分析

在 NumPy 中,除了可以使用通用函数对数组进行比较、逻辑等运算之外,还可以使用统计函数对数组进行排序、去重、求最大和最小值以及求均值等统计分析。

①排序

  • NumPy 的排序方式主要可以概括为直接排序和间接排序两种。
  • 直接排序指对数值直接进行排序;间接排序是指根据一个或多个键对数据集进行排序。
  • 在 NumPy 中,直接排序通常是使用 sort 函数,间接排序通常是使用 argsort 函数和 lexsort 函数。
  • sort 函数是较为常用的排序方法,无返回值。如果目标函数是一个视图,那么原始数据将会被修改。
  • 当使用 sort 函数排序时,用户可以指定一个 axis 参数,使得 sort 函数可以沿着指定轴对数据集进行排序。
  • 使用 argsort 函数和 lexsort 函数,可以在给定一个或多个键时,得到一个由整数构成的索引数组,索引值表示数据在新的序列中的位置。
  • lexsort 函数可以一次性对满足多个键的数组执行间接排序。

②去重与重复数据

  • 在统计分析的工作中,难免会出现 “脏” 数据的情况。重复数据就是 “脏” 数据的情况之一。
  • 如果一个一个地手动删除,那么将会耗时费力且效率低。
  • 在 NumPy 中,可以通过 unique 函数查找出数组中的唯一值并返回已排序的结果。
  • 另一种情况,在统计分析中也经常遇到,即需要将一个数据重复若干次。
  • 在 NumPy 中主要使用 tile 函数和 repeat 函数实现数据重复。

tile 函数的基本使用格式如下。

numpy.tile(A, reps)

tile 函数主要有两个参数。

  • 参数 A 接收 array_like,表示输入的数组。

  • 参数 reps 接收 array_like,表示指定数组的重复次数。

repeat 函数的基本使用格式如下。

numpy.repeat(a, repeats, axis=None)

repeat 函数主要有 3 个参数。

  • 参数 a 接收 array_like,表示输入的数组。

  • 参数 repeats 接收 int 或整数的数组,表示每个元素的重复次数。

  • 参数 axis 接收 int,表示用于指定沿着哪个轴进行重复。

tile 函数和 repeat 函数的主要区别在于,tile 函数是对数组进行重复操作,repeat 函数是对数组中的每个元素进行重复操作。

③统计函数

  • 在 NumPy 中,有许多可以用于统计分析的函数。
  • 常见的统计函数有 sum、mean、std、var、min 和 max 等。
  • 几乎所有的统计函数在针对二维数组计算的时候都需要注意轴的概念。
  • 当 axis 参数为 0 时,表示沿着纵轴进行计算;当 axis 为 1 时,表示沿着横轴进行计算。
  • 默认情况下,函数并不按照任一轴向计算,而是计算一个总值。
  • 聚合计算将直接显示计算的最终结果,在 NumPy 中,cumsum 函数和 cumprod 函数采用不聚合计算,产生一个由中间结果组成的数组。

# 5. 函数代码示例

# 数组对象
import numpy as np
# 一维数组
arr1=np.array([1,2,3,4])
print('一维数组arr1:',arr1)
结果:
arr1: [1 2 3 4]
# 二维数组
arr2=np.array([[1,2,3],[1,2,3]])
print('二维数组arr2:')
print(arr2)
结果:
二维数组arr2:
[[1 2 3]
 [1 2 3]]
print('二维数组的形状shape:',arr2.shape)
print('二维数组的类型dtype:',arr2.dtype)
print('二维数组的类型dtype:',arr2.dtype)
print('二维数组的类型size:',arr2.size)
print('二维数组的存储空间itemsize:',arr2.itemsize)
结果:
二维数组的形状shape: (2, 3)
二维数组的类型dtype: int32
二维数组的类型size: 6
二维数组的存储空间itemsize: 4