为何使用 NumPy?
NumPy 旨在提供一个比传统 Python 列表快 50 倍的数组对象。
NumPy 中的数组对象称为 ndarray
,它提供了许多支持函数,使得利用 ndarray
非常容易。
为什么 NumPy 比列表快?
与列表不同,NumPy 数组存储在内存中的一个连续位置,因此进程可以非常有效地访问和操纵它们。
这种行为在计算机科学中称为引用的局部性
检查 NumPy 版本
版本字符串存储在 __version__
属性中。
import numpy as np
print(np.__version__)
创建 NumPy ndarray 对象
NumPy 用于处理数组。 NumPy 中的数组对象称为 ndarray
。
我们可以使用 array()
函数创建一个 NumPy ndarray
对象。
type(): 这个内置的 Python 函数告诉我们传递给它的对象的类型。像上面的代码一样,它表明 arr
是 numpy.ndarray
类型。
要创建 ndarray
,我们可以将列表、元组或任何类似数组的对象传递给 array()
方法,然后它将被转换为 ndarray
数组中的维
数组中的维是数组深度(嵌套数组)的一个级别。
嵌套数组:指的是将数组作为元素的数组
只有一个元素(没有中括号)为0——D数组
import numpy as np
arr = np.array(61)
print(arr)
检查维数?
NumPy 数组提供了 ndim
属性,该属性返回一个整数,该整数会告诉我们数组有多少维。
更高维的数组
数组可以拥有任意数量的维。
在创建数组时,可以使用 ndmin
参数定义维数。
实例
创建一个有 5 个维度的数组,并验证它拥有 5 个维度:
import numpy as np
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
print('number of dimensions :', arr.ndim)
在此数组中,最里面的维度(第 5 个 dim)有 4 个元素,第 4 个 dim 有 1 个元素作为向量,第 3 个 dim 具有 1 个元素是与向量的矩阵,第 2 个 dim 有 1 个元素是 3D 数组,而第 1 个 dim 有 1 个元素,该元素是 4D 数组。
访问 3-D 数组
要访问 3-D 数组中的元素,我们可以使用逗号分隔的整数来表示元素的维数和索引。
实例
访问第一个数组的第二个数组的第三个元素:
import numpy as np
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr[0, 1, 2]
负索引
使用负索引从尾开始访问数组。
实例
打印第二个维中的的最后一个元素:
import numpy as np
arr = np.array([[1,2,3,4,5], [6,7,8,9,10]])
print('Last element from 2nd dim: ', arr[1, -1])
裁切数组
python 中裁切的意思是将元素从一个给定的索引带到另一个给定的索引。
我们像这样传递切片而不是索引:[start:end]
。
我们还可以定义步长,如下所示:[start:end:step]
。
如果我们不传递 start,则将其视为 0。
如果我们不传递 end,则视为该维度内数组的长度。
如果我们不传递 step,则视为 1
负裁切
使用减号运算符从末尾开始引用索引:
实例
从末尾开始的索引 3 到末尾开始的索引 1,对数组进行裁切:
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[-3:-1])
结果:[5 6]
实例
从两个元素裁切索引 1 到索引 4(不包括),这将返回一个 2-D 数组
import numpy as np
arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr[0:2, 1:4])
结果:[[2 3 4]
[7 8 9]]
NumPy 中的数据类型
NumPy 有一些额外的数据类型,并通过一个字符引用数据类型,例如 i
代表整数,u
代表无符号整数等。
以下是 NumPy 中所有数据类型的列表以及用于表示它们的字符。
i
- 整数b
- 布尔u
- 无符号整数f
- 浮点c
- 复合浮点数m
- timedeltaM
- datetimeO
- 对象S
- 字符串U
- unicode 字符串V
- 固定的其他类型的内存块 ( void )-
检查数组的数据类型
NumPy 数组对象有一个名为
dtype
的属性,该属性返回数组的数据类型: -
用已定义的数据类型创建数组
我们使用
array()
函数来创建数组,该函数可以使用可选参数:dtype
,它允许我们定义数组元素的预期数据类型:实例
用数据类型字符串创建数组:
import numpy as np arr = np.array([1, 2, 3, 4], dtype='S') print(arr) print(arr.dtype)
结果:[b'1' b'2' b'3' b'4']
|S1 -
假如值无法转换会怎样?
如果给出了不能强制转换元素的类型,则 NumPy 将引发 ValueError。
ValueError:在 Python 中,如果传递给函数的参数的类型是非预期或错误的,则会引发 ValueError。
实例
无法将非整数字符串(比如 'a')转换为整数(将引发错误)
转换已有数组的数据类型
更改现有数组的数据类型的最佳方法,是使用 astype()
方法复制该数组。
astype()
函数创建数组的副本,并允许您将数据类型指定为参数。
数据类型可以使用字符串指定,例如 'f'
表示浮点数,'i'
表示整数等。或者您也可以直接使用数据类型,例如 float
表示浮点数,int
表示整数。
实例
将数据类型从整数更改为布尔值:
import numpy as np
arr = np.array([1, 0, 3])
newarr = arr.astype(bool)
print(newarr)
print(newarr.dtype)
副本和视图之间的区别
副本和数组视图之间的主要区别在于副本是一个新数组,而这个视图只是原始数组的视图。
副本拥有数据,对副本所做的任何更改都不会影响原始数组,对原始数组所做的任何更改也不会影响副本。
视图不拥有数据,对视图所做的任何更改都会影响原始数组,而对原始数组所做的任何更改都会影响视图。
检查数组是否拥有数据
如上所述,副本拥有数据,而视图不拥有数据,但是我们如何检查呢?
每个 NumPy 数组都有一个属性 base
,如果该数组拥有数据,则这个 base 属性返回 None
。
否则,base
属性将引用原始对象。
获取数组的形状
NumPy 数组有一个名为 shape
的属性,该属性返回一个元组,每个索引具有相应元素的数量。
实例
利用 ndmin
使用值 1,2,3,4 的向量创建有 5 个维度的数组,并验证最后一个维度的值为 4:
import numpy as np
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
print('shape of array :', arr.shape)
结果为:[[[[[1 2 3 4]]]]]
shape of array : (1, 1, 1, 1, 4)
元组的形状代表什么?
每个索引处的整数表明相应维度拥有的元素数量。
上例中的索引 4,我们的值为 4,因此可以说第 5 个 ( 4 + 1 th) 维度有 4 个元素。
数组重塑
重塑意味着更改数组的形状。
数组的形状是每个维中元素的数量。
通过重塑,我们可以添加或删除维度或更改每个维度中的元素数量。
从 1-D 重塑为 3-D
实例
将以下具有 12 个元素的 1-D 数组转换为 3-D 数组。
最外面的维度将具有 2 个数组,其中包含 3 个数组,每个数组包含 2 个元素:
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(2, 3, 2)
print(newarr)
结果为:[[[ 1 2]
[ 3 4]
[ 5 6]]
[[ 7 8]
[ 9 10]
[11 12]]]
我们可以重塑成任何形状吗?
是的,只要重塑所需的元素在两种形状中均相等。
我们可以将 8 元素 1D 数组重塑为 2 行 2D 数组中的 4 个元素,但是我们不能将其重塑为 3 元素 3 行 2D 数组,因为这将需要 3x3 = 9 个元素。
实例
尝试将具有 8 个元素的 1D 数组转换为每个维度中具有 3 个元素的 2D 数组(将产生错误):
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(arr.reshape(2, 4).base)
上面的例子返回原始数组,因此它是一个视图
未知的维
您可以使用一个“未知”维度。
这意味着您不必在 reshape 方法中为维度之一指定确切的数字。
传递 -1
作为值,NumPy 将为您计算该数字
注释:我们不能将 -1
传递给一个以上的维度。
展平数组
展平数组(Flattening the arrays)是指将多维数组转换为 1D 数组。
我们可以使用 reshape(-1)
来做到这一点
NumPy 数组迭代
如果我们迭代一个 n-D 数组,它将逐一遍历第 n-1 维。
如需返回实际值、标量,我们必须迭代每个维中的数组。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
for x in arr:
for y in x:
print(y)
使用 nditer() 迭代数组
import numpy as np
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
for x in np.nditer(arr):
print(x)
结果为:1
2
3
4
5
6
7
8
迭代不同数据类型的数组
我们可以使用 op_dtypes
参数,并传递期望的数据类型,以在迭代时更改元素的数据类型。
NumPy 不会就地更改元素的数据类型(元素位于数组中),因此它需要一些其他空间来执行此操作,该额外空间称为 buffer,为了在 nditer()
中启用它,我们传参 flags=['buffered']
import numpy as np
arr = np.array([1, 2, 3])
for x in np.nditer(arr, flags=['buffered'], op_dtypes=['S']):
print(x
以不同的步长迭代
我们可以使用过滤,然后进行迭代。
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for x in np.nditer(arr[:, ::2]):
print(x)
使用 ndenumerate() 进行枚举迭代
枚举是指逐一提及事物的序号。
有时,我们在迭代时需要元素的相应索引,对于这些用例,可以使用 ndenumerate()
方法。
import numpy as np
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for idx, x in np.ndenumerate(arr):
print(idx, x)
(0, 0) 1
(0, 1) 2
(0, 2) 3
(0, 3) 4
(1, 0) 5
(1, 1) 6
(1, 2) 7
(1, 3) 8
NumPy 数组连接
连接 NumPy 数组
连接意味着将两个或多个数组的内容放在单个数组中。
在 SQL 中,我们基于键来连接表,而在 NumPy 中,我们按轴连接数组。
我们传递了一系列要与轴一起连接到 concatenate()
函数的数组。如果未显式传递轴,则将其视为 0。
import numpy as np
arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
arr = np.concatenate((arr1, arr2), axis=1)
print(arr)
[[1 2 5 6]
[3 4 7 8]]
使用堆栈函数连接数组
堆栈与级联相同,唯一的不同是堆栈是沿着新轴完成的。
我们可以沿着第二个轴连接两个一维数组,这将导致它们彼此重叠,即,堆叠(stacking)。
我们传递了一系列要与轴一起连接到 concatenate()
方法的数组。如果未显式传递轴,则将其视为 0。
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr = np.stack((arr1, arr2), axis=1)
print(arr)
[[1 4]
[2 5]
[3 6]]
沿行堆叠
NumPy 提供了一个辅助函数:hstack()
沿行堆叠
沿列堆叠
NumPy 提供了一个辅助函数:vstack()
沿列堆叠。
沿高度堆叠(深度)
NumPy 提供了一个辅助函数:dstack()
沿高度堆叠,该高度与深度相同。
NumPy 数组拆分
拆分是连接的反向操作。
连接(Joining)是将多个数组合并为一个,拆分(Spliting)将一个数组拆分为多个。
我们使用 array_split()
分割数组,将要分割的数组和分割数传递给它。
注释:返回值是一个包含n个数组的数组。
如果数组中的元素少于要求的数量,它将从末尾进行相应调整
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6])
newarr = np.array_split(arr, 4)
print(newarr)
[array([1, 2]), array([3, 4]), array([5]), array([6])]
拆分为数组
array_split()
方法的返回值是一个包含每个分割的数组。
如果将一个数组拆分为 3 个数组,则可以像使用任何数组元素一样从结果中访问它们:
此外,您可以指定要进行拆分的轴。
下面的例子还返回三个 2-D 数组,但它们沿列 (axis=1) 分割。
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
newarr = np.array_split(arr, 3, axis=1)
print(newarr)
[array([[ 1],
[ 4],
[ 7],
[10],
[13],
[16]]), array([[ 2],
[ 5],
[ 8],
[11],
[14],
[17]]), array([[ 3],
[ 6],
[ 9],
[12],
[15],
[18]])]
另一种解决方案是使用与 hstack()
相反的 hsplit()
。
提示:vsplit()
和 dsplit()
可以使用与 vstack()
和 dstack()
类似的替代方法。
NumPy 数组搜索
搜索数组
您可以在数组中搜索(检索)某个值,然后返回获得匹配的索引。
要搜索数组,请使用 where()
方法。
会返回一个元组
搜索排序
有一个名为 searchsorted()
的方法,该方法在数组中执行二进制搜索,并返回将在其中插入指定值以维持搜索顺序的索引。
假定 searchsorted()
方法用于排序数组。
import numpy as np
arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7)
print(x)
例子解释:应该在索引 1 上插入数字 7,以保持排序顺序。
该方法从左侧开始搜索,并返回第一个索引,其中数字 7 不再大于下一个值。
import numpy as np
arr = np.array([6, 7, 8, 9])
x = np.searchsorted(arr, 7, side='right')
print(x)
例子解释:应该在索引 2 上插入数字 7,以保持排序顺序。
该方法从右边开始搜索,并返回第一个索引,其中数字 7 不再小于下一个值。
多个值
要搜索多个值,请使用拥有指定值的数组。
NumPy 数组排序
数组排序
排序是指将元素按有序顺序排列。
有序序列是拥有与元素相对应的顺序的任何序列,例如数字或字母、升序或降序。
NumPy ndarray 对象有一个名为 sort()
的函数,该函数将对指定的数组进行排序。
注释:此方法返回数组的副本,而原始数组保持不变。
您还可以对字符串数组或任何其他数据类型进行排序:
import numpy as np
arr = np.array([[3, 2, 4], [5, 0, 1]])
print(np.sort(arr))
[[2 3 4]
[0 1 5]]
NumPy 数组过滤
数组过滤
从现有数组中取出一些元素并从中创建新数组称为过滤(filtering)。
在 NumPy 中,我们使用布尔索引列表来过滤数组。
布尔索引列表是与数组中的索引相对应的布尔值列表。
如果索引处的值为 True
,则该元素包含在过滤后的数组中;如果索引处的值为 False
,则该元素将从过滤后的数组中排除
import numpy as np
arr = np.array([61, 62, 63, 64, 65])
x = [True, False, True, False, True]
newarr = arr[x]
print(newarr)
通常和循环得出布尔值使用
直接从数组创建过滤器
上例是 NumPy 中非常常见的任务,NumPy 提供了解决该问题的好方法。
我们可以在条件中直接替换数组而不是 iterable 变量,它会如我们期望地那样工作。
import numpy as np
arr = np.array([61, 62, 63, 64, 65])
filter_arr = arr > 62
newarr = arr[filter_arr]
print(filter_arr)
print(newarr)
[False False True True True]
[63 64 65]
NumPy 中的随机数
生成随机数
NumPy 提供了 random 模块来处理随机数。
from numpy import random
x = random.randint(100)
print(x)
生成随机浮点
random 模块的 rand()
方法返回 0 到 1 之间的随机浮点数。
生成随机数组
在 NumPy 中,我们可以使用上例中的两种方法来创建随机数组。
生成有 3 行的 2-D 数组,每行包含 5 个从 0 到 100 之间的随机整数
from numpy import random
x = random.randint(100, size=(3, 5))
print(x)
从数组生成随机数
choice()
方法使您可以基于值数组生成随机值。
choice()
方法将数组作为参数,并随机返回其中一个值。
from numpy import random
x = random.choice([3, 5, 7, 9], size=(3, 5))
print(x)
NumPy ufuncs
什么是 ufuncs?
ufuncs 指的是“通用函数”(Universal Functions),它们是对 ndarray 对象进行操作的 NumPy 函数。