Python NumPy 基础

🍦 NumPy是用于处理数组的Python库,具有在线性代数、傅里叶变换等领域工作的功能,由Travis Oliphant于2005年创建。

1 NumPy

  • Numpy
    • 通过import关键字将其导入应用程序,通常以np别名替代。
    • 检查NumPy版本,版本字符串存储在__version__属性下。
1
2
3
4
5
6
import numpy as np                             # 导入时使用关键字别名

arr = np.array([1, 2])
print(arr)

print(np.__version__) # 检查NumPy版本

2 创建数组

  • 创建数组
    • NumPy中的数组对象称为ndarray,使用数组对象的array()函数创建NumPy对象。
    • type()用于显示数组类型numpy.ndarray,数组中的维度是一级数组深度(嵌套数组)。
      • 0-D数组:零维数组,又叫标量,数组中的每个值都是一个0-D数组。
      • 1-D数组:一维数组,以零维数组作为元素的数组,是最基本的数组。
      • 2-D数组:二维数组,以一维数组作为元素的数组,用于表示二阶张量。
      • 3-D数组:三维数组,以二维数组作为元素的数组,用于表示三阶张量。
      • 高维数组:数组可有任意数量的维度,创建时使用ndmin参数定义维数。
    • 二阶张量又叫矩阵,使用ndim检查数组的维数,返回整数的属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np

arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr)) # <class 'numpy.ndarray'>
print("-----------------------")

arr0 = np.array(30) # 0-D
print(arr0)
arr1 = np.array((1, 2, 3)) # 1-D
print(arr1)
arr2 = np.array([[1, 2], [3, 4]])
print(arr2) # 2-D
arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(arr3) # 3-D
arr5 = np.array([1, 2, 3, 4], ndmin=5)
print(arr5) # 5-D
print("-----------------------")

print(arr0.ndim) # 检查数组的维数
print(arr1.ndim)
print(arr2.ndim)
print(arr3.ndim)
print(arr5.ndim)

2-1 数组索引

  • 数组索引
    • 数组索引与访问数组元素相同,通过引用索引号访问数组元素。
    • 索引从0开始,第一个元素索引为0,第二个元素索引为1,以此类推。
    • 二维数组和三维数组都使用逗号分隔的整数来表示元素的维度和索引。
    • 二维数组索引可以想象为具有行和列的表,行表示维度,索引表示列。
    • 可以使用负索引从末尾访问数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

arr1 = np.array([1, 2, 3, 4, 5])
print(arr1[0]) # 访问一维数组元素
print(arr1[1])
print(arr1[2])
print(arr1[3])

arr2 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr2[0, 1]) # 访问二维数组元素,第一行第二列的元素

arr3 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr3[0, 1, 2]) # 访问三维数组元素,第一个数组的第二个数组的第三个元素

print(arr2[1, -1]) # 访问二维数组元素,第二行的最后一个元素

2-2 数组切片

  • 数组切片
    • 格式:[start: end][start: end: step],结果包括开始索引,但不包括结束索引。
    • start默认为0,end在维度中考虑数组的长度,step默认为1,使用负号可从末尾引用索引。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

arr1 = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr1[1: 5]) # 索引1到5的元素,不包括5
print(arr1[3:]) # 索引3到数组末尾的元素切片
print(arr1[: 4]) # 索引开始到4的切片元素,不包括4
print(arr1[-5: -1]) # 负索引从-1开始,索引末尾-1到-5的元素,不包括-1
print(arr1[1: 5: 1]) # 索引1到5的所有元素,其中步长为1
print(arr1[:: 2]) # 索引整个数组中步长为2的所有元素
print("---------")

arr2 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr2[1, 1: 3]) # 第二个元素开始,索引1到3的元素,不包括3
print(arr2[0: 2, 2]) # 两个元素中返回索引2
print(arr2[0: 2, 1: 4]) # 两个元素中,返回索引1到4的元素,不包括4,返回一个二维数组

2-3 数据类型

  • 数据类型
    • Python中的数据类型:float、integer、boolean、complex、strings
    • NumPy模块也有一些额外的数据类型,且是指代具有一个字符的数据类型。
      • b(布尔值)、c(复数)、f(浮点数)、i(整数)、m(分钟时间增量,时间差异)、u(无符号整数)。
      • M(日期时间)、O(对象)、S(字符串)、U(Unicode字符串)、V(其他类型的固定内存块void)。
    • NumPy数组对象有个dtype属性,用于返回数组的数据类型。
    • array()创建具有已定义数据类型的数组,带可选参数dtype,允许定义数组元素的预期数据类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np

arr1 = np.array([1, 2, 3])
print(arr1.dtype) # 获取数组对象的数据类型
arr2 = np.array(["apple", "peach", "grape"])
print(arr2.dtype) # 获取包含字符串数组的数据类型

arr3 = np.array([1, 2, 3], dtype="S") # 创建一个数据类型为字符串的数组
# print(arr3)
print(arr3.dtype)
arr4 = np.array([1, 2, 3], dtype="i4") # 创建一个数据类型为4字节整数的数组
# print(arr4)
print(arr4.dtype)

2-4 类型转换

  • 类型转换
    • 若给定类型无法转换元素,NumPy将引发ValueError(传递给函数的参数类型意外或不正确时显示)。
    • 使用astype()方法制作数组的副本,允许将数据类型指定为参数,可以更改现有数组的数据类型。
    • 用字符串指定数据类型,如f(浮点数)、i(整数)等,或直接使用数据类型,如floatint等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

# arr1 = np.array(["a", "2"], dtype="i") # 像a这样的非整数字符串不能转换为整数,会引发错误
arr2 = np.array([1.1, 2.1])
arr3 = arr2.astype("i") # 通过使用i作为参数值将数据类型从浮点数更改为整数
print(arr3)
print(arr3.dtype)

arr4 = arr2.astype(int) # 通过使用int作为参数值将数据类型从浮点数更改为整数
print(arr4)
print(arr4.dtype)

arr5 = np.array([1, 0, 3]) # 将数据类型从整数更改为布尔值
arr6 = arr5.astype(bool)
print(arr6)
# print(arr6.dtype)

3 副本视图

  • 副本视图
    • 副本是一个新数组,而视图只是原始数组的视图。
      • 副本拥有数据,对副本所做的更改不会影响原始数组,对原始数组所做的更改不会影响副本。
      • 视图没有数据,对视图所做的更改将会影响原始数组,对原始数组所做的更改也会影响视图。
    • 每个NumPy数组都有base属性,如果数组拥有数据,那么返回None,否则base属性引用原始对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import numpy as np

arr1 = np.array([1, 2, 3, 4, 5])
arr2 = arr1.copy() # 创建一个副本
arr1[0] = 3 # 更改原始数组
print(arr1) # 显示两个数组
print(arr2) # 副本不应受到对原始数组所做更改的影响

arr3 = arr1.view() # 创建一个视图
arr1[0] = 6 # 更改原始数组
print(arr1) # 显示两个数组
print(arr3) # 视图应该受到对原始数组所做更改的影响

arr4 = arr1.view() # 创建一个视图
arr4[0] = 1 # 更改视图
print(arr1) # 显示两个数组
print(arr4) # 原始数组应该受到对视图所做更改的影响

arr5 = arr1.copy() # 打印base属性的值,检查数组是否拥有数据
arr6 = arr1.view()
# print(arr5.base) # 副本返回None
print(arr6.base) # 视图返回原始数组

4 形状重塑

  • 形状
    • 数组形状是每个维度中元素的数量,NumPy数组有shape属性。
    • shape属性返回一个元组,每个索引都有与之对应元素的数量。
    • 形状元组:每个索引处的整数都表示相应维度具有的元素数量。
1
2
3
4
5
6
7
import numpy as np

arr1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) # 二维数组的形状(2, 4),2个维度,维度一有2个元素,维度二有4个元素
print(arr1.shape)
arr2 = np.array([1, 2, 3, 4], ndmin=5) # 使用值为1、2、3、4的ndmin向量创建一个5维数组,并打印最后一维的值
# print(arr2)
print(arr2.shape)
  • 重塑
    • 数组重塑意味着改变数组形状,可添加或删除维度,或更改每个维度元素的数量。
    • 只要数组重塑所需要的元素在两种形状中都相同,就可以将数组重塑成任何形状。
    • 不必为reshape方法的其中一个维度指定确切的数字,拥有未知维度,作为-1值传递。
    • 扁平化数组意味着将多维数组转换为一维数组,可以使用reshape(-1)来做到这一点。
    • 改变数组形状还有flatten、revel函数,rot90、flip、fliplr和flipud等则可重新排列元素。
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
import numpy as np

arr1 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
arr2 = arr1.reshape(4, 3) # 从一维重塑到二维
print(arr2) # 最外层维度有4个数组,每个数组包含3个元素
print("-----------------")

arr3 = arr1.reshape(2, 3, 2) # 从一维重塑到三维
print(arr3) # 最外层维度有2个数组,其中包含3个数组,每个数组有2个元素
print("-----------------")

arr4 = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(arr4.reshape(2, 4).base) # 检查返回的数组是副本或视图,返回原始数组,是视图
print("-----------------")

# arr5 = arr4.reshape(3, 3)
# print(arr5) # 8个元素的1-D数组转换为每个维度具有3个元素的2-D数组,会引发错误

arr6 = arr4.reshape(2, 2, -1) # 8个元素的1-D数组转换为2x2元素的3-D数组,不能传递-1值到多个维度
print(arr6)
print("-----------------")

arr7 = np.array([[1, 2, 3], [4, 5, 6]])
arr8 = arr7.reshape(-1) # 将数组转换为一维数组
print(arr8)

5 连接拆分

  • 连接
    • SQL中基于键连接表,NumPy中通过轴连接数组。
    • 通过concatenate()函数将数组与轴一起进行传递连接,参数axis默认为0。
    • 使用堆栈函数stack()连接数组(堆叠,一个轴在另一个轴上),参数axis默认0。
    • hstack()(沿行堆叠)、vstack()(沿列堆叠)、dstack()(沿高度或深度堆叠)。
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
27
28
import numpy as np

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
arr3 = np.concatenate((arr1, arr2)) # 连接两个一维数组
print(arr3)
print("-------------")

arr4 = np.array([[1, 2], [3, 4]])
arr5 = np.array([[5, 6], [7, 8]])
arr6 = np.concatenate((arr4, arr5), axis=1) # 连接两个二维数组
print(arr6)
print("-------------")

arr7 = np.stack((arr1, arr2), axis=1) # 堆叠
print(arr7)
print("-------------")

arrh = np.hstack((arr1, arr2)) # 沿行堆叠
print(arrh)
print("-------------")

arrv = np.vstack((arr1, arr2)) # 沿列堆叠
print(arrv)
print("-------------")

arrd = np.dstack((arr1, arr2)) # 沿高度或深度堆叠
print(arrd)
  • 拆分
    • 拆分是连接的逆操作,array_split()方法用于拆分数组。
      • 如果数组的元素少于所需要的元素,那么将相应地从末尾进行自动调整。
      • 也可以使用split()方法,但若元素较少,不会自动调整,将返回错误。
    • array_split()方法的返回值是一个数组,其中包含每个数组拆分为一个数组。
      • 若将一个数组拆分为3个数组,可以像访问任何数组元素一样从结果中进行访问。
      • 可指定要围绕哪个轴进行拆分,使用axis参数进行拆分,或使用hsplit()替代。
      • vstack()dstack()函数对应沿列拆分vsplit()以及沿高度拆分dsplit()
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
27
28
29
30
31
32
import numpy as np

arr1 = np.array([1, 2, 3, 4, 5, 6])
arr2 = np.array_split(arr1, 3) # 将一维数组拆分为3部分
print(arr2) # 返回一个包含3个数组的数组
arr3 = np.array_split(arr1, 4) # 将一维数组拆分为4部分
print(arr3) # 数组元素少于所需的元素
arr4 = np.split(arr1, 6) # 将一维数组拆分为3部分
print(arr4)
print("------------------------------------------------------------------------")

print(arr2[0]) # 打印拆分后的数组
print(arr2[1])
print(arr2[2])
print("------------------------------------------------------------------------")

arr5 = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])
arr6 = np.array_split(arr5, 3) # 将二维数组拆分为3个二维数组
print(arr6)
print("------------------------------------------------------------------------")

arr7 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
arr8 = np.array_split(arr7, 3) # 将二维数组拆分为3个二维数组
print(arr8)
print("------------------------------------------------------------------------")

arr9 = np.array_split(arr7, 3, axis=1) # 将二维数组沿行拆分为3个二维数组
print(arr9)
print("------------------------------------------------------------------------")

arrh = np.hsplit(arr7, 3) # 将二维数组沿行拆分为3个二维数组
print(arrh)

6 数组迭代

  • 数组迭代
    • 迭代意味着一个一个地遍历元素,在NumPy中处理多维数组时,使用for循环可以进行迭代。
    • 若迭代一个n-D数组,将遍历n-1维,要返回实际值,即标量,必须在每个维度中迭代数组。
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
import numpy as np

arr1 = np.array([1, 2, 3])
for x in arr1: # 迭代一维数组的元素
print(x)
print("------------")

arr2 = np.array([[1, 2, 3], [4, 5, 6]])
for y in arr2: # 迭代二维数组的元素
print(y)
print("------------")

for x in arr2: # 迭代二维数组的每个标量元素
for y in x:
print(y)
print("------------")

arr3 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
for x in arr3: # 迭代三维数组的元素
print(x)
print("------------")

for x in arr3: # 迭代三维数组的每个标量元素
for y in x:
for z in y:
print(z)
  • 迭代方法
    • nditer()是一个帮助函数,可以解决迭代中的一些基本问题。
      • 使用op_dtypes参数并将预期的数据类型传递给它,可以在迭代时更改元素的数据类型。
      • 元素在数组中时,NumPy不会就地更改元素的数据类型,需要一些其他空间来执行此操作。
      • 其他空间即缓冲区,为启用额外空间,还需要使用nditer()函数的flags=["buffered"]
    • 使用过滤可以以不同的步长进行迭代,若需元素的相应索引,可用ndenumerate()进行枚举迭代。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np

arr1 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
for x in np.nditer(arr1): # 遍历3-D数组
print(x)
print("---------")

arr2 = np.array([1, 2, 3]) # 作为字符串遍历数组
for x in np.nditer(arr2, flags=["buffered"], op_dtypes=["S"]):
print(x)
print("---------")

arr3 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for x in np.nditer(arr3[:, ::2]): # 每跳过1个元素,遍历2-D数组的每个标量元素
print(x)
print("---------")

for idx, x in np.ndenumerate(arr2): # 枚举一维数组元素
print(idx, x)
print("---------")

for idx, x in np.ndenumerate(arr3): # 枚举二维数组元素
print(idx, x)

7 数组搜索

  • 数组搜索
    • where()方法可以进行数组搜索。
    • searchsorted()方法:考虑先插入,再排序,最后索引。
      • 数组中执行二进制搜索,并返回将插入指定值的索引以保持搜索顺序。
      • 默认情况下返回左侧索引,使用side="right"可以改为返回右侧索引。
      • 如果需要搜索多个值,那么可以使用具有指定值的数组进行数组的搜索。
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
27
import numpy as np

arr1 = np.array([1, 2, 3, 4, 5, 4, 4])
val4 = np.where(arr1 == 4) # 查找值为4的索引
print(val4) # 返回元组(array([3, 5, 6], )),值4出现在索引的3、5和6位置处
print("-----------------------------------")
even = np.where(arr1 % 2 == 0) # 查找值为偶数的索引
print(even)
print("-----------------------------------")

arr2 = np.array([6, 7, 8, 9])
insl = np.searchsorted(arr2, 7) # 查找应插入值7的索引
print(insl) # 索引从左侧开始,并返回第一个索引
print("-----------------------------------")
insr = np.searchsorted(arr2, 7, side="right")
print(insr) # 索引从右侧开始,并返回第一个索引
print("-----------------------------------")

arr3 = np.array([1, 3, 5, 7])
ins1 = np.searchsorted(arr3, 0) # 返回0
print(ins1)
print("-----------------------------------")
ins2 = np.searchsorted(arr3, [8, 9]) # 返回数组[4 4]
print(ins2)
print("-----------------------------------")
ins3 = np.searchsorted(arr3, [2, 4, 6]) # 查找应插入值2、4和6的索引,返回数组[1 2 3]
print(ins3)

8 数组排序

  • 数组排序
    • NumPy的ndarray对象有一个sort()函数,可以对指定的数组进行排序。
    • sort()函数可以对字符串数组、布尔数组或任何其他数据类型进行排序。
    • 若对二维数组使用sort()函数,那么二维数组中的两个数组都将被排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

arr1 = np.array([3, 2, 0, 1]) # 对数组排序
print(np.sort(arr1)) # 返回数组arr1的副本,保持原始数组不变
print("-------------------------")

arr2 = np.array(["grape", "apple", "peach"])
print(np.sort(arr2)) # 按字母顺序对数组排序
print("-------------------------")

arr3 = np.array([True, False, True, False])
print(np.sort(arr3)) # 对布尔数组排序
print("-------------------------")

arr4 = np.array([[3, 2, 4], [5, 0, 1]])
print(np.sort(arr4))

9 数组过滤器

  • 数组过滤器
    • 从现有数组中取出一些元素,并从中创建一个新数组,称为数组过滤。
    • 布尔索引列表过滤数组
      • 如果索引处的值是True,则该元素包含在过滤后的数组中。
      • 如果索引处的值是False,则该元素从过滤后的数组中排除。
    • 根据条件创建过滤器数组,可以在条件中直接替换数组而不是可迭代变量。
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
import numpy as np

arr1 = np.array([30, 31, 32, 33])
boo1 = [True, False, True, False]
new1 = arr1[boo1] # 对True和False值进行了硬编码
print(new1) # 返回[30 32],新过滤器仅包含过滤器数组具有value的True值
print("--------------------------")

filter_arr1 = [] # 创建空列表
for element in arr1: # 遍历数组arr1中的每个元素
if element > 31: # 元素大于31,将值设为True,否则为False
filter_arr1.append(True)
else:
filter_arr1.append(False)
arr2 = arr1[filter_arr1]
print(filter_arr1) # [False, False, True, True]
print("--------------------------")
print(arr2) # 返回[32 33]
print("--------------------------")

filter_arr2 = arr1 > 31 # 在条件中直接替换数组
arr3 = arr1[filter_arr2]
print(filter_arr2)
print("--------------------------")
print(arr3)

Python NumPy 基础
https://stitch-top.github.io/2021/03/01/python/python04-python-numpy-ji-chu/
作者
Dr.626
发布于
2021年3月1日 00:37:24
许可协议