CodeRoadMap
路线图学习路径文章题库资源社区

浏览

首页路线图学习路径知识库题库文章资源社区我的学习
CodeRoadMap

中文编程学习导航:路线图、讲义与题库,进度可同步。

路线图学习路径文章题库社区

© 2026 CodeRoadMap

津ICP备2026012044号-1|coderoadmap@126.com
首页/Python 100 天/68.NumPy的应用-1

课程目录

  1. 0101.初识Python
  2. 0202.第一个Python程序
  3. 0303.Python语言中的变量
  4. 0404.Python语言中的运算符
  5. 0505.分支结构
  6. 0606.循环结构
  7. 0707.分支和循环结构实战
  8. 0808.常用数据结构之列表-1
  9. 0909.常用数据结构之列表-2
  10. 1010.常用数据结构之元组
  11. 1111.常用数据结构之字符串
  12. 1212.常用数据结构之集合
  13. 1313.常用数据结构之字典
  14. 1414.函数和模块
  15. 1515.函数应用实战
  16. 1616.函数使用进阶
  17. 1717.函数高级应用
  18. 1818.面向对象编程入门
  19. 1919.面向对象编程进阶
  20. 2020.面向对象编程应用
  21. 2121.文件读写和异常处理
  22. 2222.对象的序列化和反序列化
  23. 2323.Python读写CSV文件
  24. 2424.Python读写Excel文件-1
  25. 2525.Python读写Excel文件-2
  26. 2626.Python操作Word和PowerPoint文件
  27. 2727.Python操作PDF文件
  28. 2828.Python处理图像
  29. 2929.Python发送邮件和短信
  30. 3030.正则表达式的应用
  31. 3131.Python语言进阶
  32. 3232-33.Web前端入门
  33. 3334-35.玩转Linux操作系统
  34. 3436.关系型数据库和MySQL概述
  35. 3537.SQL详解之DDL
  36. 3638.SQL详解之DML
  37. 3739.SQL详解之DQL
  38. 3840.SQL详解之DCL
  39. 3941.MySQL新特性
  40. 4042.视图、函数和过程
  41. 4143.索引
  42. 4244.Python接入MySQL数据库
  43. 4345.Hive实战
  44. 4446.Django快速上手
  45. 4547.深入模型
  46. 4648.静态资源和Ajax请求
  47. 4749.Cookie和Session
  48. 4850.制作报表
  49. 4951.日志和调试工具栏
  50. 5052.中间件的应用
  51. 5153.前后端分离开发入门
  52. 5254.RESTful架构和DRF入门
  53. 5355.RESTful架构和DRF进阶
  54. 5456.使用缓存
  55. 5557.接入三方平台
  56. 5658.异步任务和定时任务
  57. 5759.单元测试
  58. 5860.项目上线
  59. 5961.网络数据采集概述
  60. 6062.用Python获取网络资源-1
  61. 6162.用Python解析HTML页面-2
  62. 6263.并发编程在爬虫中的应用
  63. 6363.Python中的并发编程-1
  64. 6463.Python中的并发编程-2
  65. 6563.Python中的并发编程-3
  66. 6664.使用Selenium抓取网页动态内容
  67. 6765.爬虫框架Scrapy简介
  68. 6866.数据分析概述
  69. 6967.环境准备
  70. 7068.NumPy的应用-1
  71. 7169.NumPy的应用-2
  72. 7270.NumPy的应用-3
  73. 7371.NumPy的应用-4
  74. 7472.深入浅出pandas-1
  75. 7573.深入浅出pandas-2
  76. 7674.深入浅出pandas-3
  77. 7775.深入浅出pandas-4
  78. 7876.深入浅出pandas-5
  79. 7977.深入浅出pandas-6
  80. 8078.数据可视化-1
  81. 8179.数据可视化-2
  82. 8280.数据可视化-3
  83. 8381.浅谈机器学习
  84. 8482.k最近邻算法
  85. 8583.决策树和随机森林
  86. 8684.朴素贝叶斯算法
  87. 8785.回归模型
  88. 8886.K-Means聚类算法
  89. 8987.集成学习算法
  90. 9088.神经网络模型
  91. 9189.自然语言处理入门
  92. 9290.机器学习实战
  93. 9391.团队项目开发的问题和解决方案
  94. 9492.Docker容器技术详解
  95. 9593.MySQL性能优化
  96. 9694.网络API接口设计
  97. 9795.使用Django开发商业项目
  98. 9896.软件测试和自动化测试
  99. 9997.电商网站技术要点剖析
  100. 10098.项目部署上线和性能调优
  101. 10199.面试中的公共问题
  102. 102100.补充内容
第 70 课1 天

68.NumPy的应用-1

Numpy 是一个开源的 Python 科学计算库,用于快速处理任意维度的数组。Numpy 支持常见的数组和矩阵操作,对于同样的数值计算任务,使用 NumPy

课程内容

NumPy的应用-1

Numpy 是一个开源的 Python 科学计算库,用于快速处理任意维度的数组。Numpy 支持常见的数组和矩阵操作,对于同样的数值计算任务,使用 NumPy 不仅代码要简洁的多,而且 NumPy 在性能上也远远优于原生 Python,至少是一到两个数量级的差距,而且数据量越大,NumPy 的优势就越明显。

NumPy 最为核心的数据类型是ndarray,使用ndarray可以处理一维、二维和多维数组,该对象相当于是一个快速而灵活的大数据容器。NumPy 底层代码使用 C 语言编写,解决了 GIL 的限制,ndarray在存取数据的时候,数据与数据的地址都是连续的,这确保了可以进行高效率的批量操作,性能上远远优于 Python 中的list;另一方面ndarray对象提供了更多的方法来处理数据,尤其获取数据统计特征的方法,这些方法也是 Python 原生的list没有的。

准备工作

  1. 启动 JupyterLab

    jupyter lab
    

    提示:在启动 JupyterLab 之前,建议先安装好数据分析相关依赖项,包括之前提到的三大神器以及相关依赖项。如果使用 Anaconda,则无需单独安装,可以通过 Anaconda 的 Navigator 来启动。

  2. 导入

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    

    说明:如果已经启动了 JupyterLab 但尚未安装相关依赖库,例如尚未安装numpy,可以在单元格中输入%pip install numpy并运行该单元格来安装 NumPy。当然,我们也可以在单元格中输入%pip install numpy pandas matplotlib把 Python 数据分析三个核心的三方库都安装上。注意上面的代码,我们不仅导入了 NumPy,还将 pandas 和 matplotlib 库一并导入了。

创建数组对象

创建ndarray对象有很多种方法,下面我们介绍一些常用的方法。

方法一:使用array函数,通过list创建数组对象

代码:

array1 = np.array([1, 2, 3, 4, 5])
array1

输出:

array([1, 2, 3, 4, 5])

代码:

array2 = np.array([[1, 2, 3], [4, 5, 6]])
array2

输出:

array([[1, 2, 3],
       [4, 5, 6]])

方法二:使用arange函数,指定取值范围和跨度创建数组对象

代码:

array3 = np.arange(0, 20, 2)
array3

输出:

array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

方法三:使用linspace函数,用指定范围和元素个数创建数组对象,生成等差数列

代码:

array4 = np.linspace(-1, 1, 11)
array4

输出:

array([-1. , -0.8, -0.6, -0.4, -0.2,  0. ,  0.2,  0.4,  0.6,  0.8,  1. ])

方法四:使用logspace函数,生成等比数列

代码:

array5 = np.logspace(1, 10, num=10, base=2)
array5

注意:等比数列的起始值是 $\small{2^1}$ ,等比数列的终止值是 $\small{2^{10}}$ ,num是元素的个数,base就是底数。

输出:

array([   2.,    4.,    8.,   16.,   32.,   64.,  128.,  256.,  512., 1024.])

方法五:通过fromstring函数从字符串提取数据创建数组对象

代码:

array6 = np.fromstring('1, 2, 3, 4, 5', sep=',', dtype='i8')
array6 

输出:

array([1, 2, 3, 4, 5])

方法六:通过fromiter函数从生成器(迭代器)中获取数据创建数组对象

代码:

def fib(how_many):
    a, b = 0, 1
    for _ in range(how_many):
        a, b = b, a + b
        yield a


gen = fib(20)
array7 = np.fromiter(gen, dtype='i8')
array7

输出:

array([   1,    1,    2,    3,    5,    8,   13,   21,   34,   55,   89,
        144,  233,  377,  610,  987, 1597, 2584, 4181, 6765])

方法七:使用numpy.random模块的函数生成随机数创建数组对象

产生 10 个 $\small{[0, 1)}$ 范围的随机小数,代码:

array8 = np.random.rand(10)
array8

输出:

array([0.45556132, 0.67871326, 0.4552213 , 0.96671509, 0.44086463,
       0.72650875, 0.79877188, 0.12153022, 0.24762739, 0.6669852 ])

产生 10 个 $\small{[1, 100)}$ 范围的随机整数,代码:

array9 = np.random.randint(1, 100, 10)
array9

输出:

array([29, 97, 87, 47, 39, 19, 71, 32, 79, 34])

产生 20 个 $\small{\mu=50}$ , $\small{\sigma=10}$ 的正态分布随机数,代码:

array10 = np.random.normal(50, 10, 20)
array10

输出:

array([55.04155586, 46.43510797, 20.28371158, 62.67884053, 61.23185964,
       38.22682148, 53.17126151, 43.54741592, 36.11268017, 40.94086676,
       63.27911699, 46.92688903, 37.1593374 , 67.06525656, 67.47269463,
       23.37925889, 31.45312239, 48.34532466, 55.09180924, 47.95702787])

产生 $\small{[0, 1)}$ 范围的随机小数构成的 3 行 4 列的二维数组,代码:

array11 = np.random.rand(3, 4)
array11

输出:

array([[0.54017809, 0.46797771, 0.78291445, 0.79501326],
       [0.93973783, 0.21434806, 0.03592874, 0.88838892],
       [0.84130479, 0.3566601 , 0.99935473, 0.26353598]])

产生 $\small{[1, 100)}$ 范围的随机整数构成的三维数组,代码:

array12 = np.random.randint(1, 100, (3, 4, 5))
array12

输出:

array([[[94, 26, 49, 24, 43],
        [27, 27, 33, 98, 33],
        [13, 73,  6,  1, 77],
        [54, 32, 51, 86, 59]],

       [[62, 75, 62, 29, 87],
        [90, 26,  6, 79, 41],
        [31, 15, 32, 56, 64],
        [37, 84, 61, 71, 71]],

       [[45, 24, 78, 77, 41],
        [75, 37,  4, 74, 93],
        [ 1, 36, 36, 60, 43],
        [23, 84, 44, 89, 79]]])

方法八:创建全0、全1或指定元素的数组

使用zeros函数,代码:

array13 = np.zeros((3, 4))
array13

输出:

array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])

使用ones函数,代码:

array14 = np.ones((3, 4))
array14

输出:

array([[1., 1., 1., 1.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])

使用full函数,代码:

array15 = np.full((3, 4), 10)
array15

输出:

array([[10, 10, 10, 10],
       [10, 10, 10, 10],
       [10, 10, 10, 10]])

方法九:使用eye函数创建单位矩阵

代码:

np.eye(4)

输出:

array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])

方法十:读取图片获得对应的三维数组

代码:

array16 = plt.imread('guido.jpg')
array16

输出:

array([[[ 36,  33,  28],
        [ 36,  33,  28],
        [ 36,  33,  28],
        ...,
        [ 32,  31,  29],
        [ 32,  31,  27],
        [ 31,  32,  26]],

       [[ 37,  34,  29],
        [ 38,  35,  30],
        [ 38,  35,  30],
        ...,
        [ 31,  30,  28],
        [ 31,  30,  26],
        [ 30,  31,  25]],

       [[ 38,  35,  30],
        [ 38,  35,  30],
        [ 38,  35,  30],
        ...,
        [ 30,  29,  27],
        [ 30,  29,  25],
        [ 29,  30,  25]],

       ...,

       [[239, 178, 123],
        [237, 176, 121],
        [235, 174, 119],
        ...,
        [ 78,  68,  56],
        [ 75,  67,  54],
        [ 73,  65,  52]],

       [[238, 177, 120],
        [236, 175, 118],
        [234, 173, 116],
        ...,
        [ 82,  70,  58],
        [ 78,  68,  56],
        [ 75,  66,  51]],

       [[238, 176, 119],
        [236, 175, 118],
        [234, 173, 116],
        ...,
        [ 84,  70,  61],
        [ 81,  69,  57],
        [ 79,  67,  53]]], dtype=uint8)

说明:上面的代码读取了当前路径下名为guido.jpg 的图片文件,计算机系统中的图片通常由若干行若干列的像素点构成,而每个像素点又是由红绿蓝三原色构成的,刚好可以用三维数组来表示。读取图片用到了matplotlib库的imread函数。

数组对象的属性

size属性:获取数组元素个数。

代码:

array17 = np.arange(1, 100, 2)
array18 = np.random.rand(3, 4)
print(array16.size)
print(array17.size)
print(array18.size)

输出:

1125000
50
12

shape属性:获取数组的形状。

代码:

print(array16.shape)
print(array17.shape)
print(array18.shape)

输出:

(750, 500, 3)
(50,)
(3, 4)

dtype属性:获取数组元素的数据类型。

代码:

print(array16.dtype)
print(array17.dtype)
print(array18.dtype)

输出:

uint8
int64
float64

ndarray对象元素的数据类型可以参考如下所示的表格。

ndim属性:获取数组的维度。

代码:

print(array16.ndim)
print(array17.ndim)
print(array18.ndim)

输出:

3
1
2

itemsize属性:获取数组单个元素占用内存空间的字节数。

代码:

print(array16.itemsize)
print(array17.itemsize)
print(array18.itemsize)

输出:

1
8
8

nbytes属性:获取数组所有元素占用内存空间的字节数。

代码:

print(array16.nbytes)
print(array17.nbytes)
print(array18.nbytes)

输出:

1125000
400
96

数组的索引运算

和 Python 中的列表类似,NumPy 的ndarray对象可以进行索引和切片操作,通过索引可以获取或修改数组中的元素,通过切片操作可以取出数组的一部分,我们把切片操作也称为切片索引。

普通索引

类似于 Python 中list类型的索引运算。

代码:

array19 = np.arange(1, 10)
print(array19[0], array19[array19.size - 1])
print(array19[-array20.size], array19[-1])

输出:

1 9
1 9

代码:

array20 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
array20[2]

输出:

array([7, 8, 9])

代码:

print(array20[0][0])
print(array20[-1][-1])

输出:

1
9

代码:

print(array20[1][1])
print(array20[1, 1])

输出:

5
5

代码:

array20[1][1] = 10
array20

输出:

array([[ 1,  2,  3],
       [ 4, 10,  6],
       [ 7,  8,  9]])

代码:

array20[1] = [10, 11, 12]
array20

输出:

array([[ 1,  2,  3],
       [10, 11, 12],
       [ 7,  8,  9]])

切片索引

切片索引是形如[开始索引:结束索引:跨度]的语法,通过指定开始索引(默认值无穷小)、结束索引(默认值无穷大)和跨度(默认值1),从数组中取出指定部分的元素并构成新的数组。因为开始索引、结束索引和步长都有默认值,所以它们都可以省略,如果不指定步长,第二个冒号也可以省略。一维数组的切片运算跟 Python 中的list类型的切片非常类似,此处不再赘述,二维数组的切片可以参考下面的代码,相信非常容易理解。

代码:

array20[:2, 1:]

输出:

array([[ 2,  3],
       [11, 12]])

代码:

array20[2, :]

输出:

array([7, 8, 9])

代码:

array20[2:, :]

输出:

array([[7, 8, 9]])

代码:

array20[:, :2]

输出:

array([[ 1,  2],
       [10, 11],
       [ 7,  8]])

代码:

array20[::2, ::2]

输出:

array([[1, 3],
       [7, 9]])

代码:

array20[::-2, ::-2]

输出:

array([[9, 7],
       [3, 1]])

关于数组的索引和切片运算,大家可以通过下面的两张图来增强印象,这两张图来自《利用Python进行数据分析》一书,它是 pandas 库的作者 Wes McKinney 撰写的 Python 数据分析领域的经典教科书,有兴趣的读者可以购买和阅读原书。

图1:二维数组的普通索引

图2:二维数组的切片索引

花式索引

花式索引是用保存整数的数组充当一个数组的索引,这里所说的数组可以是 NumPy 的ndarray,也可以是 Python 中list、tuple等可迭代类型,可以使用正向或负向索引。

代码:

array19[[0, 1, 1, -1, 4, -1]]

输出:

array([1, 2, 2, 9, 5, 9])

代码:

array20[[0, 2]]

输出:

array([[1, 2, 3],
       [7, 8, 9]])

代码:

array20[[0, 2], [1, 2]]

输出:

array([2, 9])

代码:

array20[[0, 2], 1]

输出:

array([2, 8])

布尔索引

布尔索引就是通过保存布尔值的数组充当一个数组的索引,布尔值为True的元素保留,布尔值为False的元素不会被选中。布尔值的数组可以手动构造,也可以通过关系运算来产生。

代码:

array19[[True, True, False, False, True, False, False, True, True]]

输出:

array([1, 2, 5, 8, 9])

代码:

array19 > 5

输出:

array([False, False, False, False, False,  True,  True,  True,  True])

代码:

~(array19 > 5)

输出:

array([ True,  True,  True,  True,  True, False, False, False, False])

说明:~运算符可以对布尔数组中的布尔值进行逻辑取反,也就是原来的True会变成False,原来的False会变成True。

代码:

array19[array19 > 5]

输出:

array([6, 7, 8, 9])

代码:

array19 % 2 == 0

输出:

array([False,  True, False,  True, False,  True, False,  True, False])

代码:

array19[array19 % 2 == 0]

输出:

array([2, 4, 6, 8])

代码:

(array19 > 5) & (array19 % 2 == 0)

输出:

array([False, False, False, False, False,  True, False,  True, False])

说明:&运算符可以作用于两个布尔数组,如果两个数组对应元素都是True,那么运算的结果就是True,否则就是False,该运算符的运算规则类似于 Python 中的 and 运算符,只不过作用的对象是两个布尔数组。

代码:

array19[(array19 > 5) & (array19 % 2 == 0)]

输出:

array([6, 8])

代码:

array19[(array19 > 5) | (array19 % 2 == 0)]

输出:

array([2, 4, 6, 7, 8, 9])

说明:|运算符可以作用于两个布尔数组,如果两个数组对应元素都是False,那么运算的结果就是False,否则就是True,该运算符的运算规则类似于 Python 中的 or 运算符,只不过作用的对象是两个布尔数组。

代码:

array20[array21 % 2 != 0]

输出:

array([1, 3, 5, 7, 9])

关于索引运算需要说明的是,切片索引虽然创建了新的数组对象,但是新数组和原数组共享了数组中的数据,简单的说,无论你通过新数组对象或原数组对象修改数组中的数据,修改的其实是内存中的同一块数据。花式索引和布尔索引也会创建新的数组对象,而且新数组复制了原数组的元素,新数组和原数组并不是共享数据的关系,这一点可以查看数组对象的base属性,有兴趣的读者可以自行探索。

案例:通过数组切片处理图像

学习基础知识总是比较枯燥且没有成就感的,所以我们还是来个案例为大家演示下上面学习的数组索引和切片操作到底有什么用。前面我们说到过,可以用三维数组来表示图像,那么通过图像对应的三维数组进行操作,就可以实现对图像的处理,如下所示。

读入图片创建三维数组对象。

guido_image = plt.imread('guido.jpg')
plt.imshow(guido_image)

对数组的0轴进行反向切片,实现图像的垂直翻转。

plt.imshow(guido_image[::-1])

对数组的1轴进行反向切片,实现图像的水平翻转。

plt.imshow(guido_image[:,::-1])

通过切片操作实现抠图,将吉多大叔的头抠出来。

plt.imshow(guido_image[30:350, 90:300])

通过切片操作实现降采样。

plt.imshow(guido_image[::10, ::10])
← 上一课67.环境准备下一课 →69.NumPy的应用-2