NumPy入门讲座(1):基本概念

1. NumPy 的家族

NumPy 是 SciPy 家族的一员,而且是最重要的成员。SciPy 家族(见下图)是一个专门应用于数学、科学和工程领域的开源的 Python 生态圈。NumPy 最初是 SciPy 的一部分,后来独立出来了。SciPy 家族的主体,可以概括为 MSN 这三个字母,你要是喜欢足球的话,一定会联想到巴萨的梅西、苏亚雷斯和内马尔这个MSN三剑客组合。我喜欢把 Matplotlib、SciPy 和 NumPy 叫做 MSN 组合,并专门写了一篇博文,名字就叫《数学建模三剑客MSN》
在这里插入图片描述

NumPy 的安装,非常简单,直接使用 pip 命令安装即可。通常,安装 NumPy 的时候,也会顺便安装 SciPy 模块、matplotlib 模块。

PS D:>python –m pip install numpy
PS D:>python –m pip install scipy
PS D:>python –m pip install matplotlib

使用 NumPy 时,我们习惯把它简写成 np。提醒大家注意:pip 命令需要在命令行窗口中运行,而不是在下图所示的 IDEL 窗口中。 在 IDEL 窗口中可以交互式执行 Python 语句,是学习 Python 的有力工具。
在这里插入图片描述

2. NumPy 是数据处理和科学计算的基础

NumPy 是 Python 科学计算的基础软件包,提供多了维数组对象,多种派生对象(掩码数组、矩阵等)以及用于快速操作数组的函数及 API,它包括数学、逻辑、数组形状变换、排序、选择、I/O 、离散傅立叶变换、基本线性代数、基本统计运算、随机模拟等等。

和 Python 的列表相比,NumPy 拥有明显的速度优势。NumPy 底层使用 C 语言编写,内置了并行运算功能,并且内部解除了 GIL(全局解释器锁)。这意味着:

  • 其对数组的操作速度不受 Python 解释器的限制
  • 当系统有多个 CPU 时,NumPy 可以自动并行计算

NumPy 的数据组织结构,尤其是数组(numpy.ndarray),几乎已经成为所有数据处理与机器学习的标准数据结构了。越来越多的基于 Python 的机器学习和数据处理软件包使用 NumPy 数组,虽然这些工具通常都支持 Python 的原生数组(即列表——在不冲突的前提下,我可能会混用数组和列表)作为参数,但它们在处理之前会还是会将输入的数组转换为 NumPy 数组,而且也通常输出为 NumPy 数组。在 Python 的圈子里,NumPy 的重要性和普遍性日趋增强。换句话说,为了高效地使用当今机器学习和数据处理等基于 Python 的工具包,你只知道如何使用 Python 的原生数组是不够的,还需要知道如何使用 NumPy 数组。
在这里插入图片描述
上面这一张图,展示的是 Python 旗下用于图像视觉处理、2D绘图、3D渲染、数据处理、机器学习等领域比较有名的5个工具模块,都深度依赖 NumPy 数组。可以说,没有NumPy的基础,任何人都很难用好上述这5个工具库。

  • OpenCV:目前以人脸识别、自动驾驶等技术为代表的人工智能方兴未艾,其背后的图像和视觉处理,几乎都离不开 OpenCV,而 OpenCV 库中图像的数据结构,从 CV2 之后,全面转向了 NumPy,用 OpenCV 打开图像文件,得到的就是 NumPy 数组
  • OpenGL:在三维领域大名鼎鼎的OpenGL,更是深度依赖NumPy,如果没有NumPy,我们无法想象如何操作动辄几万、几十万,甚至几百万的顶点数据集
  • Pandas:这个是当下非常流行的数据分析工具包,相信很多人都是从Pandas开始接触数据处理的,而Pandas整个就是基于NumPy之上的扩展
  • Matplotlib:作为NumPy生态圈的重要成员,二者关系自然是密不可分的
  • scikit-learn:机器学习领域应用最广泛的工具包,则是建立在NumPy/SciPy/Matplotlib之上的,同样深度依赖NumPy

3. NumPy 数组 VS Python 列表

学过 Python 的同学都知道,Python 的列表操作非常灵活,而 NumPy 数组继承了 Python 数组操作便捷、灵活的特点,又具有极高的、接近 C 语言的运行效率。可以说,NumPy 数组是专为处理科学数据而生的。

  • NumPy 数组中的元素必须具有相同的数据类型,Python 列表的元素类型则不受限制;
  • NumPy 数组一旦创建,其元素数量不可再改变,Python 列表的元素则可以动态增减;
  • NumPy 数组和 Python 同样操作简单、灵活,但前者内置方法更多、运行速度更快。

4. NumPy 数组的数据类型

NumPy 支持的数据类型主要有整型(integrate)、浮点型(float)、布尔型(bool)和复数型(complex),每一种数据类型根据占用内存的字节数又分为多个不同的子类型。当然,NumPy 也支持自定义类型,我们在后面讲解数组排序的时候,再讨论自定义类型。
在这里插入图片描述
咱们来演示一下如何查看、指定数据类型。

>>> a = np.array([0,1,2,3])
>>> a.dtype
dtype('int32')
>>> a = np.array([0,1,2,3.0])
>>> a.dtype
dtype('float64')
>>> a = np.array([0,1,2,3+0j])
>>> a.dtype
dtype('complex128')
>>> a = np.array([0,1,2,3], dtype=np.int16)
>>> a.dtype
dtype('int16')
>>> a = np.array([0,1,2,3], dtype=np.uint8)
>>> a.dtype
dtype('uint8')

dtype 是数组的属性之一,可以很方便地查看数组的数据类型。创建数组时,如果不指定数据类型,numpy会根据输入数据选择合适的数据类型。指定数据类型的时候,通常可以省略类型后面的数字。如果省略数字的话,整形和无符号整形默认是32位的,浮点型默认是64位的,复数型默认是128位。

5. NumPy 数组的属性

刚才我们用 dtype 可以查看数组的数据类型,dtype 是数组对象的属性之一,除了 dtype,NumPy 数组还有其他一些属性,比如,shape,数组结构,或者叫形状;sizes,数组元素个数;itemsize,数组元素字节数;flags,数组的内存信息;real,数组实部;imag,数据虚部;data,存储区域内存地址,相当于指针。除此之外,还有一个属性,ndim,数组的维度数,也叫秩,下一节会专门讲它。属性看起来有点多,但我们只需要记住 dtypeshape 两个属性就足够了。这两个属性非常重要,重要到你可以忽略其他的属性。

属性说明
ndarray.dtype元素类型
ndarray.shape数组结构
ndarray.size元素个数
ndarray.itemsize每个元素的大小,以字节为单位
ndarray.ndim数组的维度数,也叫秩
ndarray.flags数组的内存信息
ndarray.real元素的实部
ndarray.imag元素的虚部
ndarray.data元素数组的实际存储区

下面是这些属性的演示操作:

>>> a = np.arange(24, dtype=np.complex64).reshape((2,3,4))
>>> a.dtype # 复数类型
dtype('complex64')
>>> a.shape # 2层3行4列
(2, 3, 4)
>>> a.size # 总共24个元素
24
>>> a.itemsize # 每个元素占用8个字节
8
>>> a.flags # 存储信息
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False

>>> a.real # 实部
array([[[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.]],

       [[12., 13., 14., 15.],
        [16., 17., 18., 19.],
        [20., 21., 22., 23.]]], dtype=float32)
>>> a.imag # 虚部
array([[[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]],

       [[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]]], dtype=float32)
>>> a.data # 内存区域地址
<memory at 0x00000157D820BC78>
>>> a.ndim # 维度数(秩)
3

6. 维、秩、轴

维,就是维度。我们说数组是几维的,就是指维度,3维的数组,其维度数,自然就是3。维度数,有一个专用名字,叫做秩,也就是上一节提到的数组属性 ndim。秩,这个名字感觉有些多余,不如维度数更容易理解。但是,轴的概念,大家一定要建立起来,并且要理解,因为轴的概念很重要。简单来说,我们可以把数组的轴,和笛卡尔坐标系的轴对应一下。

一维数组,类比于一维空间,只有一个轴,那就是0轴。
在这里插入图片描述

二维数组,类比于二维平面,有两个轴,我们习惯表示成行、列,那么行的方向就是0轴,列的方向就是1轴。
在这里插入图片描述
三维数组,类比于三维空间,有三个轴,我们习惯表示成层、行、列,那么层的方向就是0轴,行的方向就是1轴,列的方向就是2轴。
在这里插入图片描述

我们用一个求和的例子来演示一下轴概念的重要性。先来看看用 Python 的求和。

>>> a = [2,5,4,7,9,3] # python的求和函数sum(),只能对一维列表求和
>>> sum(a)
30
>>> a = [[3,5,1],[2,6,9]] # 如果是多维列表,那就会报错了
>>> sum(a)
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    sum(a)
TypeError: unsupported operand type(s) for +: 'int' and 'list'

但有时候,我们的需求会比较复杂,比如,分层求和,逐行求和,逐列求和等。这时候,Numpy 的轴概念就可以大显身手了。

>>> a = np.arange(18).reshape((3,2,3)) # 3层2行3列的结构
>>> a
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]],

       [[12, 13, 14],
        [15, 16, 17]]])
>>> np.sum(a)
153 
>>> np.sum(a, axis=0) # 层合并求和
array([[18, 21, 24],
       [27, 30, 33]])
>>> np.sum(a, axis=1) # 行合并求和
array([[ 3,  5,  7],
       [15, 17, 19],
       [27, 29, 31]])
>>> np.sum(a, axis=2) # 列合并求和
array([[ 3, 12],
       [21, 30],
       [39, 48]])
>>> np.sum(np.sum(a, axis=1), axis=1) # 分层求和方法1
array([15, 51, 87])
>>> np.sum(np.sum(a, axis=2), axis=1) # 分层求和方法2
array([15, 51, 87])

同样是求和,显然,NumPy数组要比Python列表更强大、更灵活。

7. 广播和矢量化

在讲两个概念之前,我们先思考两个问题:

  1. 整型数组各元素加1;
  2. 求两个等长整型数组对应元素之和组成的新数组。

我们先用python数组实现:

>>> x = list(range(5))
>>> for i in range(len(x)): # 遍历数组为每个元素加1
        x[i] += 1
>>> y = list(range(5,10))
>>> z = list()
>>> for i, j in zip(x, y): # 遍历两个数组,逐个元素求和
        z.append(i+j)

我们再用NumPy数组实现:

>>> a = np.arange(5)
>>> a += 1
>>> b = np.arange(5,10)
>>> c = a + b

显然,用NumPy数组实现起来,要比python数组更简洁、更清晰。这得益于于 NumPy 的两大特性:广播(broadcast)和矢量化(vectorization)。

广播和矢量化,是 NumPy 最精髓的特性,是 NumPy 的灵魂。所谓广播,就是将对数组的操作映射到每个数组元素上;矢量化可以理解为代码中没有显式的循环、索引等。NumPy数组最重要的特性是广播和矢量化,体现在性能上,就是接近C语言的运行效率,体现在代码上,则有这样的特点:

  1. 矢量化代码更简洁,更易于阅读;
  2. 代码行越少意味着出错的几率越小;
  3. 代码更接近于标准的数学符号;
  4. 矢量化代码更pythonic

在这里插入图片描述

后记

近期有很多朋友通过私信咨询有关Python学习问题。为便于交流,我在CSDN的app上创建了“Python作业辅导”大本营,面向Python初学者,为大家提供咨询服务、辅导Python作业。欢迎有兴趣的同学使用微信扫码加入。

在这里插入图片描述

从博客到公众号,每一篇、每一题、每一句、每一行代码,都坚持原创,绝不复制抄袭,这是我坚守的原则。如果喜欢,请关注我的微信公众号“Python作业辅导员”。

在这里插入图片描述

  • 20
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天元浪子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值