现在咱们已经对 NumPy 有了基本的知道,知道了 NumPy 的强壮,而且得知 NumPy 中心便是运用多维数组对数据的高效处理办法

可是你是否思考过什么是数组呢?只要了解到什么是数组,才干了解它能够处理什么问题,进而在遇到该类问题时快速挑选运用它。咱们还应该注意到多维这个概念,正如高楼有多层相同,数组有多维。辨明高楼的多层能够协助咱们不会走错家门,而理清数组的多维相同能够协助咱们更好地安排数组、操作数组、查找数据。

每个事物都存在着特色,咱们在运用这个事物时其实是针对特色进行运用的,为了更好地运用数组,使数组能够协助咱们处理详细的问题,咱们还应该了解数组的特色。例如咱们食用苹果,是针对它的饱腹、营养、味甜的特色,挑选苹果时则依赖色红、个圆等特色。

这些问题或许你比较模糊,不必着急,今天咱们就会对这些问题进行讲解。

维度、特色与轴

维度是用来描绘事物所在的空间维度。在不同领域,维度有着不同的含义。例如,在物理学中的三维空间有长度、宽度和高度三个维度;在数学中,点是零维,线是一维,平面是二维,立方体便是三维。在计算机领域中,能够用三维来表明一个人的特色,如身高、肤色和体重,每个特色对应一个维度。

从数组上讲,维度便是数的组合叠加,将任意个数字组合在一起咱们称为一维数组,将任意个一维数组组合在一起咱们称为二维数组,这样将当前维度数组视作一个单位元素去堆叠就生成了高一维的数组。

而轴便是用来描绘多维数组中的数据位置的一组直线,每一个维度对应一个轴。 轴与数组的维度相关联,经过不同的轴,咱们能够拜访数组中不同维度的数据。

在一维空间中,咱们用一个轴(一般为axis0)表明直线空间上的离散点。 在二维空间中,需求用两个轴(一般为axis0和axis1)来表明平面空间上的离散点,其间axis0表明行,axis1表明列。 在三维空间中,需求用三个轴(一般为axis0、axis1和axis2)来表明立方体空间上的离散点。

这儿需求注意,axis0一般指向最新的维度,比方三维相比二维添加了高,那么axis0便是高这个维度的轴,其他以此类推。

经过指定多个不同的轴,咱们能够在多维数组中定位和处理数据。

Numpy中ndarray到底有什么秘密?

特色是描绘事物特征或性质的概念。在不同领域,特色能够表明不同事物的特征。例如,在计算机领域中,咱们要识别合适的礼仪队员,对人进行建模。人的肤色、身高和体重便是三个不同的特色。咱们能够用一个维度的数据安排办法来表达这三个特色的数据集,也能够用联系型数据库来存储这三个特色和特色值。在数学和计算机科学中,特色类似于数据的特征,能够用于描绘数据调集的性质和特色。

举个例子,有一个二维数组(矩阵):

[[1,2,3],
[4,5,6],  
[7,8,9]]

这个数组有两个维度,能够视为平面空间上的数据。在numpy中,咱们一般用axis0和axis1来表明这两个维度。axis0表明行,axis1表明列。特色能够类比为矩阵中的元素,每个元素都代表矩阵中的一个数据点,而这个数据点能够用于描绘矩阵的性质和特征。例如,矩阵中的元素能够表明一个人的某个特色值,如肤色、身高或体重。

经过了解维度、轴和特色的概念,咱们能够更好地处理多维数组数据、描绘事物特征以及进行数学和科学计算。这些概念在数据处理、人工智能、数学建模等领域中都起着重要的效果。

什么是数组?

数组是一系列具有相同数据类型的元素组合,而且仍是有次序的。换句话来讲,数组便是一组数据元素,而且这些元素的数据类型都是相同的。咱们能够用工厂流水线来比作数组,流水线中的产品便是数据元素,它们有着相同的类型且是接连的。

许多人学习的榜首门编程言语便是 C 言语,不是说 C 言语很简略,而是 C 言语更偏向于底层。经过对 C 言语的学习,能够深刻地了解到数据在内存中的存储办法,所以运用 C 言语来诠释数组在内存中如何存储和调用是十分直观的。接下来咱们运用它来创立数组,诠释数组的本质和特色。

C 言语创立数组比较简略,如下示例代码,将一个学生的六科成果作为一个数组进行创立,并将其打印输出。

#include <stdio.h>
#include <stdlib.h>
int main(){
         int grade[6]={100,106,100,83,67,78};
         for(int i=0;i<6;i++){
                  printf("成果%d:%d",i,grade[i]);
         }
         return 0;
}

成果如下:

成果0:100
成果1:106
成果2:100
成果3:83
成果4:67
成果5:78

C 言语创立数组是经过界说创立的,但只是了解如何创立数组是不够的,更重要的是咱们还需求知道数组在内存中是如何寄存的。咱们拜访数组元素是经过下标进行拜访的,这是很常见的办法,可是下标拜访的依据是什么呢?咱们经过检查数组在内存中的地址来进行解释,看以下代码:

#include <stdio.h>
#include <stdlib.h>
int main(){
         int grade[6]={100,106,100,83,67,78};
         for(int i=0;i<6;i++){
                  printf("成果%d:%d\n",i,grade[i]);
         }
         for(int i=0;i<6;i++){
                  printf("地址%d:%x\n",i,&grade[i]);
         }
         return 0;
}

成果如下:

成果0:100
成果1:106
成果2:100
成果3:83
成果4:67
成果5:78
地址0:251df8e8
地址1:251df8ec
地址2:251df8f0
地址3:251df8f4
地址4:251df8f8
地址5:251df8fc

从打印的地址成果来看,数组在内存中是接连存储的,而且每个地址有 4 个字节的存储空间,示例如图所示:

Numpy中ndarray到底有什么秘密?

假定数组的起始地址为 0,根据打印成果,每个数据元素占 4 个字节的空间。数组在内存中是接连存储的,而且存储数据的空间是相同的。

在这个过程中,需求明确两个问题。

  • 榜首,为什么该数组的存储空间是 4 个字节?这个很好了解,该数组类型为 int 型,而 int 型在内存中一般占 4 个字节。
  • 第二,数组是怎样经过下标进行拜访元素的?在 C 言语中,指针指向的是一个内存地址。在这儿,数组名 grade 是一个指针,存储着该数组的起始地址 0(即为基地址),再经过基地址进行拜访其他数据的存储地址,因为内存地址是接连的,而且存储空间巨细一起,下标拜访便是根据地址的有序添加完成的。

Numpy中ndarray到底有什么秘密?

& 表明取址:

grade[1]=&grade[0]+4
grade[2]=&grade[0]+8

这便是 C 言语中数组在内存中的创立与拜访过程,但这只是是一维数组的创立,那么一旦对数组的维度进行添加,会怎样创立?数组中关于维度的添加其实是经过数组的嵌套完成的,在许多言语中都是支撑数组的嵌套的,这也是能够完成维度化的关键点

上述只取一名同学的成果,创立了一维数组,再另取多名同学的成果进行剖析,能够完成数据的嵌套,改动数据的维度。

#include <stdio.h>
 #include <stdlib.h>
 int main(){
         int grade[3][6]={{100,106,100,83,67,78},
 {100,106,100,83,67,78},
 {100,106,100,83,67,78}};
         for(int i=0;i<3;i++){
                  for(int j=0;j<6;j++){
                          printf("第%d名的成果%d:%d,成果存储地址%d%d:%x\n",i+1,j,grade[i][j],i+1,j,&grade[i][j]);
                  }
printf("\n");
         }
          return 0;
 }

成果如下:

第1名的成果0:100,成果存储地址10:684ff6d0
第1名的成果1:106,成果存储地址11:684ff6d4
第1名的成果2:100,成果存储地址12:684ff6d8
第1名的成果3:83,成果存储地址13:684ff6dc
第1名的成果4:67,成果存储地址14:684ff6e0
第1名的成果5:78,成果存储地址15:684ff6e4
第2名的成果0:100,成果存储地址20:684ff6e8
第2名的成果1:106,成果存储地址21:684ff6ec
第2名的成果2:100,成果存储地址22:684ff6f0
第2名的成果3:83,成果存储地址23:684ff6f4
第2名的成果4:67,成果存储地址24:684ff6f8
第2名的成果5:78,成果存储地址25:684ff6fc
第3名的成果0:100,成果存储地址30:684ff700
第3名的成果1:106,成果存储地址31:684ff704
第3名的成果2:100,成果存储地址32:684ff708
第3名的成果3:83,成果存储地址33:684ff70c
第3名的成果4:67,成果存储地址34:684ff710
第3名的成果5:78,成果存储地址35:684ff714

观察二维数组的内存成果,咱们可知数组元素在内存中是以线性接连的办法存储的,可是关于数组的拜访是经过两层的下标进行拜访,如下示意图:

Numpy中ndarray到底有什么秘密?

外层是一个含有三个元素的数组,其间每一个元素又都是有六个元素的数组,最终组成一个二维的数组。三个元素代表三个学生,而每个学生都有自身的特色,例如成果。这是契合数据的维度化的。经过数组的嵌套就能够发生多维的数组。同理,这儿内存空间是接连的,按照笼统的了解,外层的三个数组,每个数组的所占有内存空间是六个 int 型的总空间,即 24 个字节,但实际上内存中二维数组仍是线性摆放,因而下标查询仍然是根据内存有序添加来进行查找的。

grade[0][1]=&grade[0]+4
grade[1][1]=&grade[0]+24
grade[2][1]=&grade[0]+48

经过 C 言语创立数组和数组在内存中的存储办法,能够简略了解到有关数组的一些特色,我将数组的这些特色进行总结,如下:

  • 数组在内存中是线性接连的;
  • 数组中元素的数据类型是相同的,它们的存储空间巨细是相同的;
  • 多维数组的创立是经过数组的嵌套完成的,可是存储办法仍然是线性接连的。

咱们已经学习了数组的底层原理,但这并不是咱们的最终意图,运用数组才是最终意图,那么运用数组到底能有什么优点呢?

数组的优点

数据是许多方面的要素影响构成的,所以咱们在剖析数据时需求从不同的方面,即维度下手,而这些延展出来的维度会发生特色,许多特色才最终组成一个数据项。因而,数据不是单一的,用数组能够将这些数据构成一个全体进行表明。比方学生,特色有学号、年龄、性别、年级、各科成果等。本来是一个个的数据,经过数组进行创立,就能当作一个全体,一起组成学生这一数据项。因而,数组能够使数据的特色构成一个全体进行剖析

其次,数组中的多维数组的存在,使咱们能够一起对多个数据项进行全体的剖析。关于学校来说,看中的不只是是一个学生的成果,而是全体学生的成果状况,对多项数据进行整合剖析,有助于进行成果猜测与剖析。

说了许多的数组知识,这跟 Numpy 有什么联系呢?那是因为在 Numpy 这个库中最最常用、最最基础的便是数组,咱们只要先了解了普通的数组,才干更进一步地了解 Numpy 中的数组,了解到它为什么能够运用于数据剖析。

Numpy 中的数组——ndarray

在 Numpy 中重要的内核便是 ndarray 多维数组,进行数据剖析时,对数据进行运算很大程度上依赖于 ndarray。

ndarray名字中的”n”代表”多维”(Multi-dimensional),”d”代表”维度”(Dimension),”array”则指”数组”。ndarray是Numpy的中心数据结构,用于表明多维数组目标,它由一系列相同数据类型的元素组成,且每个元素占用相同巨细的内存块。ndarray是一个快速且灵敏的数据容器。

为了便利了解ndarray,下面举一个例子来说明。唐僧西天取经团队的成员编号能够经过一维数组来表明,数组名为QF_boys,数组QF_boys中存储的是数值类型的数据,别离是100,101,102,103,104。

索引 成员编号
0 100
1 101
2 102
3 103
4 104

咱们能够经过自带的索引来获取元素,例如QF_boys[0]代表的便是唐僧的工号100.

ndarray的主要特色有:

  • 多维数组办法:ndarray能够是一维、二维、或更高维度的数组,因而能够灵敏地处理杂乱的数据结构。这使得在科学计算、统计剖析、图画处理等领域中,对高维数据的表明和处理变得更加便利和天然。
  • 同一数据类型:数组中的一切元素有必要是同一种数据类型,这种强制性约束保证了数据的一起性,也使得数据的处理更为高效。因为数据类型固定,ndarray的元素在内存中存储紧凑,避免了额外的类型检查,提升了运算速度。
  • 从0开端的索引:ndarray的索引从0开端,与许多编程言语一起,例如C和C++,这为数据的拜访和处理供给了一致的规则。这种索引办法更契合数学中的矩阵表明,也使得代码更易于编写和阅览。
  • 支撑并行化和向量化运算:借助底层的优化完成,ndarray能够进行并行化和向量化运算,极大地提升了数据处理的功率。这种优化能力使得Numpy在大规模数据处理和科学计算中体现突出。
  • 存储高效:因为ndarray中一切元素的数据类型相同,数据存储在内存中是接连的,这样寻址和存取操作都变得高效。此外,ndarray支撑运用内存映射文件进行数据的读写,便于处理大规模数据集。

正因为这些特色和优势,运用ndarray能够极大地简化代码,省去了许多繁琐的循环句子,使得数据处理和计算更加简洁和高效。 经过下面这张图片,咱们能够直观知道到ndarray的数据分布图。

Numpy中ndarray到底有什么秘密?

ndarray 的常见特色有形状数据类型元素个数数组维度等等,经过这些特色,能够协助咱们更好地了解 ndarray。下面咱们就来介绍一下 ndarray 的相关特色吧!

shape

首先咱们先来学习一下 ndarray 的形状。经过获取数组的形状,咱们可知晓数组的行数和列数,便利调整数组的维度。

shape 为 Ndarray 的形状,一般由一个包含了各个维度中数组的巨细的元组表明。比方,一个二行三列的数组,它的的形状便能够由(2,3)这个元组表明。

在生活中,咱们最常运用的数组多为一维数组、二维数组以及三维数组这三种,更高维度的数组咱们一般很少运用。下面咱们就经过图示,为大家介绍一下常用的几种数组的形状都是怎样的。

一维数组示意图:

Numpy中ndarray到底有什么秘密?

经过图示,咱们能够看见一维数组的形状是水平方向的一条线。

二维数组示意图:

Numpy中ndarray到底有什么秘密?

经过观察二维数组的示意图能够发现,二维数组的形状类似于一个平面,能够当作是由多个一维数组纵向叠加而成。

下面咱们再来看看三维数组的示意图:

Numpy中ndarray到底有什么秘密?

经过观察三维数组的示意图,咱们发现三维数组的形状是一个立体图,它比二维数组又多了一个轴向,是多个二维数组在新的轴向上的堆叠。

由此咱们能够得出结论:更高维度的数组便是较低维度数组的堆叠

那么,如何检查一个 ndarray 数据目标的形状呢?

代码示例:

import numpy as np
arr=np.array([[1,2,3],[4,5,6]])  
print(arr.shape)

输出成果:

(2, 3)

能够看见咱们运用 . 加 shape 的办法成功获取到了 ndarray 的形状信息。下面咱们再来学习一下 ndarray 多维数组的维度特色吧!

ndim

ndim 是 ndarray 数组目标的维度特色,维度咱们能够了解为这个数组轴的数量或者了解为代表数组形状的元组的巨细。比方一个三行四列的数组,它的 shape 特色为(3,4),该元组的巨细为 2,咱们就能够说该数组的维度 ndim 为 2。

咱们还能够经过别的一种办法确定数组的维度,假如咱们想要获取数组中的某个元素,下标需求指定几个,数组的维度便是几。

比方,咱们有如下一个数组:

Arr=[[1 2 3]
[4 5 6]]

假如想要获取元素 2 就需求经过 Arr[0][1] 来获取,此时下标指定了两层,所以该数组的维度便为 2。了解了数组的维度,下面咱们就来看看怎样才干检查一个 ndarray 数组的维度吧!

代码示例:

import numpy as np
arr=np.array([[1,2,3],[4,5,6]])
print('数组的维度:',arr.ndim)

输出成果:

数组的维度: 2

能够看见咱们运用 . 加 ndim 的办法成功获取到了 ndarray 的维度信息。下面咱们再来学习一下 ndarray 多维数组的巨细特色吧!

size

size 为 ndarray 数组的巨细,也便是数组中的元素个数,由一个 int 型的整数表明。一般 ndarray 数组的巨细为各个维度上数组巨细的乘积,换句话说便是代表形状的元组的各个元素的乘积,比方一个三维数组,它的形状为(3,4,2),据此咱们就能够知道它的巨细为 24。

下面咱们就来看一下怎样经过代码检查一个数组的巨细吧!

代码示例:

import numpy as np
arr=np.array([[1,2,3],[4,5,6]])
print('数组的巨细:',arr.size)

输出成果:

数组的巨细: 6

一起,数组的形状shape也与数组的其他特色有一定的联系,表明数组形状的元组的巨细便是该数组的维度ndim,比方一个二行三列的数组的维度便为2;元组内各个元素的乘积便是该数组的巨细size,比方这个二行三列的数组的巨细便为6。也便是说,咱们知道一个数组的形状,便能够推导出数组的维度以及巨细这两个特色。

能够看见咱们运用 . 加 size 的办法成功获取到了 ndarray 的维度信息。下面咱们再来学习一下 ndarray 多维数组的数据类型吧!

dtype

dtype 是 ndarray 的数据类型,经过该特色咱们能够知道 ndarray 中存储数据的数据类型。

Numpy 的数据类型主要分为以下几种。

  • 整数类型:包含 int8、int16、int32、int64,这些类型别离表明 8 位、16 位、32 位、64 位的带符号整数。
  • 浮点类型:包含 float16、float32、float64,这些类型别离表明 16 位、32 位、64 位的浮点数。
  • 复数类型:包含 complex64、complex128,这些类型别离表明 64 位和 128 位的复数。
  • 布尔类型:即 bool_,它只要两个取值:True 和 False。
  • 字符串类型:即 str_,用于存储字符串。

下面咱们就来看看如何经过代码的办法检查一个数组的数据类型吧!

代码示例:

import numpy as np
arr=np.array([[1,2,3],[4,5,6]])  
print(arr.dtype)

输出成果:

int32

相同咱们也能够借助 . 加 dtype 的办法检查 ndarray 的数据类型。

由此咱们知道,假如想要经过代码检查一个数组的各种特色,咱们只需求经过 ndarray.特色名的办法便能够获取对应的特色值。

了解了 ndarray 数组的特色,那么 C 言语数组与 ndarray 数组有什么异同之处呢?

C 言语数组和 ndarray 数组的异同

ndarray 数组不单单是由数据所构成的,实际上它是一个数组目标。示例图如下:

Numpy中ndarray到底有什么秘密?

ndarray 目标分为两个部分:一个部分是 header、一个是 data。header 部分能够了解为数组特色块,里边有着 ndarray 数组目标所需求的一些特色,比方该数组的步长、数组的形状、数组中数据的类型,等等。data 部分就能够了解为 C 言语中的数组了,存储的是数据。

针对 data 部分,也是契合上面所说的有关数组的特色的。

  • 数组在内存中是线性接连的。
  • 数组所存储的数据的类型是一起的,也便是在内存中元素所占用的空间巨细是不变的。
  • 多维数组的创立是经过数组的嵌套完成的,可是存储办法仍然是线性接连的。

关于 header 部分,便是数组所需求的特色部分,经过这些特色咱们能够知道有关数组的一些基础的信息。比方检查 dtype 特色获取数据类型信息,运用 shape 特色知晓数组形状。运用这些特色,数组能够经过索引快速拜访所需数据。除此之外,header 中还存在其他特色,比方说字节序、读写权限、C-order(行优先存储)等。

接下来介绍一下 ndarray 的数据类型。

ndarray 中的数据类型

咱们在学习 Python 时学习了整型、浮点型、字符型等多种数据类型,NumPy 作为 Python 的扩展包,天然支撑 Python 的一切数据类型,而且还供给了更加丰富的数据类型,如 float64、int32、bool_,在 numpy 中数据类型基本上都是由数据类型和位数组成的。在 numpy 中除了界说时默许的数据类型,在实际需求时,咱们也能够改动数据类型使其成为所需求的数据类型。

改动数据类型运用的是 astype 办法。astype 办法是强制转化数据类型,可是转化之后是不改动原数组元素类型的,而是生成一个新的数组,因而下面的示例中需求经过赋值来从头构建数组。

下面咱们有一组试验的输入数据,数据类型为 int32,现在一模型要求输入数据为 float 型,该如何处理呢?

代码示例:

import numpy as np
arr=np.array([[1,2,3],[4,5,6]])  
print('原数组数据类型',arr.dtype)  
arr=arr.astype('float')  
print('强制转化之后数据类型',arr.dtype)

输出成果:

原数组数据类型 int32
强制转化之后数据类型 float64

前面咱们所看见的数组都存储的是同一数据类型的元素,可是咱们知道 NumPy 数组和结构化数据是紧密联系的,例如数据库数据、Excel 表格文件等,这些数据都有一个特色,便是一条数据中包含多个特色数据。例如一张成果表中,每条数据都包含名字、学号、成果等数据,别离对应字符串、整型、浮点型等数据类型,而在数据类型中,咱们不能从已有的数据类型中找到一个合适的数据类型来对应咱们成果表中的数据,这时候咱们就需求运用到数据类型目标来新建一个结构化数据类型

在 C 言语中,咱们学习过运用界说结构体,也便是经过 struct 界说结构类型,完成多种数据类型的封装,进而构成咱们所需求的数据类型。那么在 NumPy 中是怎样操作的呢?

NumPy 中界说结构化数据需求用到 dtype 目标。数据类型目标(Data Type Object)又称 dtype 目标,主要用来描绘数组元素的数据类型、巨细以及字节次序。一起,它也能够用来创立结构化数据。比方常见的 int64、float32 都是 dtype 目标的实例。在创立结构化数据时,咱们需求用到对应数据类型的标识码,不同的数据类型字符码是不相同的,如下所示:

字符 数据类型
b 布尔类型
i 带符号整型
u 无符号整型
f 浮点数类型
c 复数类型
m 日期类型
O 目标类型
S,a 字符串类型
U Unicode类型
V void类型

例如现在咱们需求创立一个契合成果单的结构化数据,那么咱们就需求建立名字、年龄、语文、数学、英语这五个数据字段,对应的数据类型依次为字符串、整型、浮点型、浮点型、浮点型。下面咱们来看看如何运用 dtype 来界说结构化数据而且使用。

代码示例:

import numpy as np
grade = np.dtype([('name', 'S32'), ('age', 'i'),
                  ('chinese', 'f'),
                  ('math', 'f'),
                  ('english', 'f')])
grades = np.array([("Jack", 15, 86, 90, 85), ("Tom", 16, 87, 91, 75),
                   ("Lucy", 15, 86, 90, 85)], grade)
print(grades)
[(b'Jack', 15, 86., 90., 85.) (b'Tom', 16, 87., 91., 75.) (b'Lucy', 15, 86., 90., 85.)]

能够看到,经过咱们的 dtype 界说之后的数据类型对成果单数据进行了适配。经过界说结构化数据不只是能合作咱们的数据类型,而且在之后的存取、计算方面都有许多优点。 在Numpy中,dtype(数据类型)是ndarray的关键之一,它界说了数组中元素的数据类型。dtype的存在使得Numpy能够高效地映射到机器表明,并完成与其他低级言语(如C、Fortran)的无缝集成。这种直接映射和优化保证了Numpy在数据处理和计算方面的强壮性能。Numpy支撑丰富的数据类型,包含整数、浮点数、复数等,而且允许自界说数据类型,适应各种使用场景。

总结

数组是相同数据类型的有序组合,为储存数据供给了便捷的办法,NumPy 中的中心目标便是多维数组。与 C 言语中的数组不同,Numpy 的 ndarray 数组目标由 data 数据部分和 header 头部信息两部分组成,其间数据部分就能够类比为 C 言语的数组,header 部分则存储了数组的特色等信息。经过调用数组的相关特色,咱们能够对数组的形状、维度等信息有所了解。数组的形状经过元组的办法进行表明,高维数组咱们能够了解为较低维度数组的堆叠,这些信息会协助咱们更好地了解高维数组的索引。

在运用 Numpy 的强制类型转化办法 astype 时,有一点值得咱们注意,运用该办法并不会直接对原数组进行类型转化,而是会构成一个新的满足数据类型要求的数组。

因为数组的最初被界说为是相同数据类型的组合,一旦数据类型不契合就会报错。数组关于数据类型的一致成果了它的功率,可是限制就意味着不方便,为了突破这方面的限制,自界说数据类型目标便是咱们所有必要掌握的。经过自界说数据类型目标咱们能够使数据的基本类型多样化,而且贴合日常运用习惯。

本文来自小册《根据 Python 的数据剖析与可视化》本小册链接:/book/724073…