真假美猴王-Numpy数据与Python数组的区别与联系
Numpy,是python中的一个矩阵计算包,功能类似matlab的矩阵计算。Numpy的诞生弥补了下面提到的两项的不足,numpy提供了两种基本的对象:ndarray(N-dimensional array object)和ufunc(universal function object)。Ndarray(下文统一称为数组)是存储单一数据类型的多维数组(同C语言数组直接保存数值),而ufunc则是能够对数组进行处理的函数。
Numpy和pandas有什么关系呢,numpy是做数据计算,pandas是做数据处理,pandas是在numpy的基础上,处理的类似excel和数据库的记录,比如多了index和column。
那么我们为什么要学习numpy呢,通常情况下我们获取数据的方式不同,得到的数据的各式就会多种多样,比如:文档集合、图像集合、声音片段集合等等。虽然这些数据存在明显的异构性,但将他们都处理或者看做为数字数组时,就会更易于理解和处理。举个例子:
声音片段:可以看作为时间和强度的一位数组
图像集合:可以看做存储不同区域像素值的二维数组
文本:可以通过各种方式处理成数值数组形式的可分析数据。
因此,学会高效的存储和操作数组是我们进行数据科学学习的绝对基础过程。虽然在某种程度上,Numpy数组与python内置的列表类型十分相似。但是随着数组在维度上不断变大,Numpy数组供了更强大的、更高效的存储和数值操作。Numpy几乎是整个python数据科学工具生态系统的核心。因此,不管我们对数据科学的哪个方面感兴趣,多花点时间去学习高效实用Numpy,都是很值得且必要的。
- Numpy是什么
概念:简单来说,numpy是python的一个科学计算包,包含了多维数组以及多位数组的操作。
核心:numpy的核心是ndarray对象,这个对象封装了同质数据类型的n维数组
- ndarray与python中原生的array有什么区别:
- NumPy 数组在创建时有固定的大小,不同于Python列表(可以动态增长)。更改ndarray的大小将创建一个新的数组并删除原始数据。
- NumPy 数组中的元素都需要具有相同的数据类型,因此在存储器中将具有相同的大小。数组的元素如果也是数组(可以是 Python 的原生 array,也可以是 ndarray)的情况下,则构成了多维数组。
- NumPy 数组便于对大量数据进行高级数学和其他类型的操作。通常,这样的操作比使用Python的内置序列可能更有效和更少的代码执行。
- 越来越多的用python做数据科学和数学相关的工作者都开始使用NumPy的ndarray数组代替python原生的array数组,所以学会 Numpy 的使用是必要的 。
2、查看python中numpy的功能与内容
首先导入numpy
查看numpy的帮助文档
也可以通过两个??查看更详细的帮助文档
二、python原生数组与numpy数组的区别与联系
1、对比Python数据类型和numpy数组做元素计算对比
如果想要将一个2-D数组 a 的每个元素与长度相同的另外一个数组 b 中相应位置的元素相乘,使用 Python 原生的数组实现如下:
需要使用列表流程:
- 初始化一个列表
- 将需要迭代的元素放在一个可迭代对象中
- 在用遍历的方式进行运行
- 输入运行结果
但是如果使用numpy实现的话,可以直接使用矢量化功能:
首先将导入numpy模块
将原生数组转化为ndarray数组
然后就可以直接进行运算了
矢量化代码有很多优点,其中包括:
- 矢量化代码更简洁易读
- 更少的代码行通常意味着更少的错误
- 该代码更接近地类似于标准数学符号(使得更容易,通常,以正确地编码数学构造)
- 矢量化导致更多的“Pythonic”代码。如果没有向量化,我们的代码将会效率很低,难以读取for循环。
要实现高效的数据驱动科学和计算,需要理解数据是如何被存储和操作的。接下来的内容,我们会对比python语言处理数组的过程,找出numpy的改进之处,这将是我们理解numpy的基础。
python用户往往是被其易用性所吸引,其中一个易用指出就在于动态输入。不同于C语言和Java,python在引用和定义变量之前不用提前指定变量类型。python变量的类型来源于我们所赋的值的类型。我们可以这样去理解:
在C语言中和python中,变量的存储形式如下:
直观来说,就相当于pythpn存储数据的时候,需要耗费一定的内存去存储和数据相关的信息。而这些信息是C语言的写成的,而当我们去修改变量的值时,相当于重新创建了一个变量,会在自动跑一遍C的底层代码,将数据所有信息更新,而这些底层代码很复杂,不需要我们去写,而是在python设计之初就已经全部写好,我们只要去执行变量赋值的操作就ok。这也是python好用的点之一。
那我们现在就可以看看变量赋值这个python功能背后的高效C语言的的伪代码:
- 一个引用计数,帮助python默默分配和处理内存以及分配和回收。
- 将变量的类型编码(type)
- 指定接下来的数据成员大小(len)
- 实际的整型值
而上述说到的除了值的额外信息,都存储在我们上述图片的PyObject_HEAD中。
2、列表和数组的区别于联系
列表和数组都是用来存储一些列的元素的,不同点在于,数组这个容器要求当中的元素必须保持同一数据类型,且是数字,而列表就不一样了,可以容纳多种不同的数据类型。
但我们在开篇有说到,当我们将数据处理成数值时,方便计算和其他操作。这个时候,我们需要的容器只要可以存储数值就可以,使用列表则或耗费一定的空间去存储每一个元素的“其他信息”,但当所有的元素都是数值时,这种存储方式显然不够高效。
下面我们举个例子说明:
从代码结果可以看出,列表中每一个元素的类型都是不同的,所以列表需要耗费一定的空间去存储这些信息,当数据很大的时候这种方式显然会拖慢运行的速度。
这样,我们就会发现,列表中每一个元素对存储着各自的类型信息,各自都是一个完整的对象。但是,容器中所有的元素都是一个类型时,显然这种存储方式不合适。但不得不说,这是我们的动态数据类型必须付出的代价。
动态数据类型与python的array数组和Numpy的ndarray这些不可变数据类型的适用场景:
list等可变数据类型适用于需要不断对原始数据进行修改的场景。修改时的操作在原始数据的本身进行。
array、ndarray这种不灵活的数据类型,适用于我们想要保护原始数据不被修改的场景。当对原始数组进行修改操作时,会自动新建一个数组。