【Python】Numpy详解

Numpy详解

相关教程

【Python】Numpy详解
【Python】Pandas详解
【Python】Matplotlib详解

一、Numpy介绍

数据分析三剑客之一的Numpy,是一个用于处理数组的 Python 包【基于数组对象的科学计算库】。 其全名为 “Numeric Python”,是一款开源的Python库。Numpy相当于Python中的列表(List),但只能存放相同的数据类型

引入Numpy的目的是可以计算大型的多维数组和矩阵操作,其计算能力强,运行的速度快。列表(List)需要先寻找元素的地址,再访问到元素;而Numpy的数组被存储在内存中的一个连续的位置【物理地址连续性】,可以非常有效地访问和操作它们

功能侧重】:numpy主要专注于数值计算和数组操作,提供了高效的底层计算功能,是许多科学计算和数据分析库的基础。

应用场景】:numpy在数据分析,科学计算、机器学习算法的底层实现、图像处理等领域应用广泛,例如在深度学习中,用于处理神经网络中的数据张量。

二、安装Numpy

在终端处输入以下命令

pip install numpy

三、Ndarray对象

Numpy的数组对象称为 Ndarray,它是一系列同类型数据的集合。

3.1:创建Ndarray对象

我们可以通过array()函数来创建一个Numpy ndarray对象

完整定义格式:numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

参数序号 参数及描述
1 object 任何暴露数组接口方法的对象都会返回一个数组或任何(嵌套)序列。✔
2 dtype 数组的所需数据类型,可选。✔
3 copy 可选,默认为true,对象是否被复制。
4 order C(按行)、F(按列)或A(任意,默认)。
5 subok 默认情况下,返回的数组被强制为基类数组。 如果为true,则返回子类。
6 ndmin 指定返回数组的最小维数 或 自定义维度。✔

小型案例

import numpy as np

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

print(arr)
------------------------
[1 2 3 4]
------------------------

3.2:Ndarray的维度

零维数组
import numpy as np

arr=np.array(71)
print(arr)
-------------------
71
-------------------
一维数组
import numpy as np

arr=np.array([1,2,3,4])
print(arr)
---------------------
[1 2 3 4]
---------------------
二维数组

二维数组通常也称之为矩阵二阶张量【行的元素数量要一致】

import numpy as np

arr=np.array([[1,2,3],[4,5,4]])
print(arr)
---------------------
[[1 2 3]
[4 5 4]]
---------------------
三维数组
import numpy as np

arr=np.array([[[1,2,3],[3,4,2],[4,3,1],[5,3,6]]])
print(arr)
---------------------
[[[1 2 3]
[3 4 2]
[4 3 1]
[5 3 6]]]
---------------------
生成0和1数组
  • np.ones(shape(, dtype)),生成全0的数组

  • np.zeros(shape(, dtype)),生成全1的数组

  • np.ones_like(a(, dtype)),生成像a那样维度的全0数组

  • np.zeros_like(a(, dtype)),生成像a那样维度的全1数组

    import numpy as np
    
    # 生成3行2列的全1数组
    arr1=np.ones([3,2],dtype=np.int32)
    print("np.ones生成数组:\n",arr1)
    
    # 生成和[4,2]同一维度的全1数组,即:生成二维全1数组
    arr2=np.ones_like([4,2],dtype=np.int32)
    print("np.ones_like生成数组:",arr2)
    -------------------------------
    np.ones生成数组:
     [[1 1]
     [1 1]
     [1 1]]
    np.ones_like生成数组: [1 1]
    -------------------------------
    

3.3:Ndarray常见操作

1)Numpy的基本属性
属性名称 属性解释
ndarray.ndim 检查数组维数,即是几维的数组
ndarry.shape 数组维度(形状),即几行几列
ndarray.size 数组中总的元素个数
ndarray.dtype 数组的数据类型
import numpy as np

# 二维数组
data = np.array([[1,2,3],[4,5,6]])
print(data.ndim) # 数组维度——2维
print(data.shape) # 数组形状——2行3列
print(data.size) # 数组元素个数——共6个
print(data.dtype) # 数组的数据类型——int64
-----------------------
2
(2, 3)
6
int64
-----------------------
2)Numpy的形状

定义:数组的形状是每个维中元素的数量

操作一:获取数组的形状

通过shape()函数来查看数组的形状;通过参数ndmin可以初始化数组的维度。

import numpy as np

# 原本有两个维度,现在通过ndmin参数增加至三个维度
arr=np.array([[1,2,3],[4,5,6],[7,8,9]],ndmin=3)
print(arr.shape)
--------------------
# 含有三个维度,第一个维度有1个元素 => [[1,2,3],[4,5,6],[7,8,9]]
# 第二个维度有三个元素 => [1,2,3],[4,5,6],[7,8,9]
# 第三个维度有三个元素 => 1,2,3 or 4,5,6 or 7,8,9
(1, 3, 3)
--------------------
操作二:数组的重塑

通过reshape()函数进行数组的重塑。

只要重塑的元素在两种形状中均相同。比如,可以将8元素的1D数组重塑为两行2D数组中的4个元素,但不可重塑为3元素3行2D数组。

从1维度重塑至2维度(升维)
import numpy as np

# 一维数组
arr=np.array([1,2,3,4,5,6,7,8,9])
arr2=arr.reshape(3,3)# 重塑为二维
print(arr2)
-------------------
[[1 2 3]
 [4 5 6]
 [7 8 9]]
-------------------
从2维度重塑至1维度(降维)

可以将多维数组降为 1D 数组,可以使用reshape(-1)来完成这一点。

import numpy as np

arr=np.array([[1,2,3,4],[5,6,7,8]])
arr2=arr.reshape(-1)
print(arr2)
-------------------
[1 2 3 4 5 6 7 8]
-------------------

3.4:Ndarray的访问

采用下标(索引)的方式进行访问元素。其中Numpy数组的索引是以0开头,意味着第一个元素的索引为0,第二个元素的索引为1,以此类推。【此处以二维数组为例】

import numpy as np

arr=np.array([[1,2,3],[41,5,4]])
print("第二维度中的第一个元素",arr[1,0]) #正索引:从头开始访问数组
print("倒数一个维度中的倒数第二个元素",arr[-1,-2]) # 负索引:从尾开始访问数组
-----------------------------
第二维度中的第一个元素 41
倒数一个维度中的倒数第二个元素 5
-----------------------------

3.5:Ndarray切片(裁剪)

两种基本格式:[start​ : end​] 和 [start​ : end : step]。【其中end是不包含在内的

注意:若不传start,默认从0开始;若不传end,默认到数组的末尾;若不传step,默认步长为1

import numpy as np
# 一维数组
arr=np.array([1,2,3,4])
# 二维数组
arr2=np.array([[1,2,3,4,5],[6,7,8,9,10]])

print("一维数组切片:")
print(arr[:2])	# 从索引0到索引(2-1)【不包含索引2】
print(arr[1:]) # 从索引1到末尾
print(arr[1:4:2]) # 从索引1开始到索引(4-1),步长为2 【不包含索引4】
print(arr[-3:-1]) # 从末尾开始的索引3到末尾开始的索引(-1-1)【不包含索引-1】

print("二维数组切片:")
print(arr2[1,1:4]) # 从第二个元素开始,取从索引1到索引4(不包含)的元素
print(arr2[0:2,2]) # 返回两个元素中的第2个元素
print(arr2[0:2,1:4]) # 两个元素,取各自的从索引1到索引4(不包含)的元素,构成2-D数组
------------------------
一维数组切片:
[1 2]
[2 3 4]
[2 4]
[2 3]
二维数组切片:
[7 8 9]
[3 8]
[[2 3 4]
 [7 8 9]]
------------------------

3.6:副本 vs 视图

1)副本与视图的区别

Numpy中副本与视图的主要区别:副本是一个新的数组视图是原始数组的视图

  • 副本是拥有数据:对副本所做的任何操作不会改变原始数组;同样对原始数组的任何改变不会影响副本
  • 视图不拥有数据:对视图所做的任何操作会影响原始数组;对原始数组的任何改变同样会影响视图
2)副本

通过copy()来创建副本【通过base来判断是否含有数据,若含有数据则返回None】

import numpy as np

arr=np.array([1,2,3]) # 原始数组
x=arr.copy() # 创建副本
# 对原始数组进行改变
arr[0]=17

print(arr) # 输出原始数组(已改变)
print(x) # 输出副本
print(x.base) # 判断是否含有数据
----------------------
[17  2  3]
[1 2 3]
None # 结果显示为None,表明含有数据
----------------------
3)视图

通过view()来创建副本【通过base来判断是否含有数据,若含有数据则返回None】

import numpy as np

arr=np.array([1,2,3]) # 原始数组
x=arr.view() # 视图
# 对原始数组进行改变
arr[0]=17

print(arr) # 输出原始数组(已改变)
print(x) # 输出副本
print(x.base) # 判断是否含有数据
------------------------
[17  2  3]
[17  2  3]
[17  2  3] # 结果显示不为None,表明不含有数据
------------------------

四、Numpy数据类型

类型 描述
np.bool 布尔类型(True或是FALSE)
np.int32 整数类型,32位
np.int64 整数类型,64位【默认】
np.uint32 无符号整数,32位【默认】
np.uint64 无符号整数,64位
np.float32 浮点数类型,32位
np.float64 浮点数类型,64位【默认】
S 字符串
U Unicode字符串
complex64 复数,分别用于两个32位浮点数表示实部和虚部
complex128 复数,分别用两个64位浮点数表示实部和虚部【默认】
import numpy as np

arr1=np.array([0,2,3],dtype=np.bool)
arr2=np.array([-1,2,3],dtype=np.int32)
arr3=np.array([1,2,3],dtype=np.uint32)
arr4=np.array([-1.67,2.56,3.14],dtype=np.float32)
arr5=np.array([1,2,3],dtype="S")
arr6=np.array([1,2,3],dtype="U")
arr7=np.array([-1,2,3],dtype=np.complex128)

print(arr1)
print(arr2)
print(arr3)
print(arr4)
print(arr5)
print(arr6)
print(arr7)
-----------------------------
[False  True  True]
[-1  2  3]
[1 2 3]
[-1.67  2.56  3.14]
[b'1' b'2' b'3']
['1' '2' '3']
[-1.+0.j  2.+0.j  3.+0.j]
-----------------------------

4.1:数据类型的查看

通过ndarray.dtype进行数据类型的查看

import numpy as np

arr1=np.array([0,2,3])
print(arr1.dtype)
--------------------
int64
--------------------

4.2:数据类型的转换

通过astype()进行数据类型的转换

import numpy as np

arr1=np.array([0,2,3])
arr2=arr1.astype(np.bool)
print(arr2)
----------------------
[False  True  True]
----------------------

五、Numpy 操作

5.1:遍历操作

方式一:通过for循环进行遍历
import numpy as np

arr1=np.array([1,2,3])
arr2=np.array([[1,2],[5,6]])

# 遍历一维数组
for i in arr1:
    print(i)
print("===============")
# 遍历二维数组
for x in arr2:
    for y in x:
        print(y)
------------------------
1
2
3
===============
1
2
5
6
------------------------
方式二:nditer()函数
用法一:迭代每个元素
import numpy as np

# 二维数组
arr=np.array([[1,2],[5,6]])
# nditer进行遍历
for i in np.nditer(arr):
    print(i)
-----------------
1
2
5
6
-----------------
用法二:以不同步长进行迭代
import numpy as np

# 二维数组
arr=np.array([[1,2,3],[5,6,7]])
# 在2D数组中,遍历每个维度中的元素,步长为2
for i in np.nditer(arr[:,::2]):
    print(i)
-------------------
1
3
5
7
-------------------
方式三:ndenumerate()函数

ndenumerate()函数可以指出事务的序号,适用于在迭代时需要元素的相关索引

import numpy as np

arr1=np.array([1,2,3,4]) # 一维函数
arr2=np.array([[1,2],[5,6]]) # 二维数组

# 遍历一维数组:序号 + 元素
for index,x in np.ndenumerate(arr1):
    print(index,x)
# 遍历二维数组:序号 + 元素
for index, x in np.ndenumerate(arr2):
    print(index, x)
---------------------
(0,) 1
(1,) 2
(2,) 3
(3,) 4
(0, 0) 1
(0, 1) 2
(1, 0) 5
(1, 1) 6
---------------------

5.2:连接操作

concatenate()函数

含义:连接操作指的是将【两个或多个数组】的内容放在【单个数组】中

基本格式numpy.concatenate((a1, a2, ...), axis)

在Numpy中,**相同类型的数组序列(a1,a2,…)通过按轴(axis)**进行连接【默认轴(axis)为0】

import numpy as np

# 两个数组的维度相同
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])

print("第一个数组:")
print(a)
print("第二个数组:")
print(b)

print("沿轴0(纵轴【列】)连接两个数组:")
a1=np.concatenate((a, b)) # 默认 axis=0
print(a1)

print("沿轴1(横轴【行】)连接两个数组:")
b1=np.concatenate((a, b), axis=1)
print(b1)
---------------------------
第一个数组:
[[1 2]
 [3 4]]
第二个数组:
[[5 6]
 [7 8]]
沿轴0(纵轴【列】)连接两个数组:
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
沿轴1(横轴【行】)连接两个数组:
[[1 2 5 6]
 [3 4 7 8]]
---------------------------

5.3:堆叠操作

Numpy 的堆叠操作可将多个数组按不同方式组合。主要有垂直堆叠vstack、水平堆叠hstack和深度堆叠dstack。它们分别在垂直方向、水平方向和深度方向上增加维度来堆叠数组,方便数据的合并与处理,提高数据处理效率。

方式一:stack()函数【堆叠】

基本格式numpy.stack(arrays, axis)

arrays:相同形状的数组序列

axis:返回数组中的轴,输入数组沿着它来堆叠,默认为0

import numpy as np

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

print("第一个数组:\n",arr1)
print("第二个数组:\n",arr2)

arr11=np.stack((arr1,arr2),axis=0)
arr22=np.stack((arr1,arr2),axis=1)
print("沿轴 0 (纵轴【列】)堆叠两个数组:\n",arr11)
print("沿轴 1 (横轴【行】)堆叠两个数组:\n",arr22)
------------------------------------
第一个数组:
 [[1 2]
  [3 4]]
第二个数组:
 [[5 6]
  [7 8]]
沿轴 0 (纵轴【列】)堆叠两个数组:
 [[[1 2]
  [3 4]]
  [[5 6]
  [7 8]]]
沿轴 1 (横轴【行】)堆叠两个数组:
 [[[1 2]
  [5 6]]
  [[3 4]
  [7 8]]]
------------------------------------
方式二:hstack()函数【水平堆叠】

numpy.stack函数的变体,通过堆叠来生成水平的单个数组。

import numpy as np

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

print("第一个数组:\n",arr1)
print("第二个数组:\n",arr2)

arr=np.hstack((arr1,arr2))
print("水平堆叠:\n",arr)
-------------------------------
第一个数组:
 [[1 2]
  [3 4]]
第二个数组:
 [[5 6]
  [7 8]]
水平堆叠:
 [[1 2 5 6]
  [3 4 7 8]]
-------------------------------
方式三:vstack()函数【垂直堆叠】

numpy.stack函数的变体,通过堆叠来生成竖直的单个数组。

import numpy as np

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

print("第一个数组:\n",arr1)
print("第二个数组:\n",arr2)

arr=np.vstack((arr1,arr2))
print("垂直堆叠:\n",arr)
---------------------------------
第一个数组:
 [[1 2]
 [3 4]]
第二个数组:
 [[5 6]
 [7 8]]
垂直堆叠:
 [[1 2]
 [3 4]
 [5 6]
 [7 8]]
---------------------------------
方式四:dstack()函数【深度堆叠】
import numpy as np

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

print("第一个数组:\n",arr1)
print("第二个数组:\n",arr2)

arr=np.dstack((arr1,arr2))
print("深度堆叠:\n",arr)
-------------------------------
第一个数组:
 [[1 2]
  [3 4]]
第二个数组:
 [[5 6]
  [7 8]]
深度堆叠:
 [[[1 5]
  [2 6]]
  [[3 7]
  [4 8]]]
-------------------------------

5.4:拆分操作

拆分是与连接的反向操作。我们通过split()函数array_split()函数来实现分割的操作。

区分

  • split()函数要求分割数量必须能整除数组的相应维度大小,否则会报错。
  • array_split()函数则可以接受不能整除的情况,它会尽量平均地分割数组,使得每个子数组的元素数量尽可能接近。

array_split()函数场景:

import numpy as np

arr=np.array([1,2,3,4,5,6,7])
newarr=np.array_split(arr,2) # 将arr分为两个子数组
print(newarr)
print("第一个子数组:",newarr[0])
print("第二个子数组:",newarr[1])
-------------------------------------------
[array([1, 2, 3, 4]), array([5, 6, 7])]
第一个子数组: [1 2 3 4]
第二个子数组: [5 6 7]
-------------------------------------------

split()函数场景:

import numpy as np

arr=np.array([1,2,3,4,5,6,7])
newarr=np.split(arr,2)
print(newarr)
--------------------------------------------------------------------
ERROR:ValueError: array split does not result in an equal division
--------------------------------------------------------------------

5.5:搜索操作

1)直接搜索【where()函数】

可以通过where()函数,在数组中从左开始搜索某个值,返回匹配的索引

【补充】:np.where(condition, x, y) 的作用是:

  • 如果 condition 为真,返回 x
  • 如果 condition 为假,返回 y
import numpy as np

arr=np.array([1,2,3,4,5,6,7])
# 查找值为偶数的索引
x=np.where(arr%2==1)
print(x)
--------------------------
(array([0, 2, 4, 6]),)
--------------------------
2)搜索排序【searchsorted()函数】

可以通过searchsorted() 函数,用于在一个已排序的一维数组查找指定值的插入位置(下标【从0开始】),以确保插入后数组仍然有序

  • 可以选择插入点的侧边:side='left'side='right'
  • 它适用于单个值或多个值的查找,并返回插入位置的索引。

当side=“left”时

import numpy as np

arr=np.array([1,3,3,6,21,37,97])
x=np.searchsorted(arr,3,side="left")

print(x)
-------------
1 # 下标为1的位置
-------------

当side=“right”时

import numpy as np

arr=np.array([1,3,3,6,21,37,97])
x=np.searchsorted(arr,3,side="right")

print(x)
-------------
3 # 下标为3的位置
-------------

当处理多个值时

values 数组中的每个元素都得到了它在 arr 中应该插入的位置。

import numpy as np

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

# 查找多个值的插入位置
indices = np.searchsorted(arr, values)
print(indices)
-------------------
[1 2 3]
-------------------

5.6:排序操作

通过sort()函数来实现排序操作,默认是升序

import numpy as np

arr = np.array([7, -3, 17, 71, 1])
# 排序(升序)
sorted_arr=np.sort(arr)
print(sorted_arr)
---------------------
[-3  1  7 17 71]
---------------------

倒序:先使用sort函数对数组进行升序排序,然后使用切片操作[::-1]将数组反转,从而实现倒序排列。

import numpy as np

arr = np.array([7, -3, 17, 71, 1])
sorted_arr=np.sort(arr) # 排序(升序)
arr1=sorted_arr[::-1] # 数组反转
print(arr1)
----------------------
[71 17  7  1 -3]
----------------------

5.7:去重操作

通过unique()函数实现去重,其返回一个由目标数组中唯一值排序后形成的一维数组

import numpy as np

arr = np.array([[7,-3,-1,5], [5,71,17,17]])
u_arr=np.unique(arr)
print(u_arr)
-----------------------
[-3 -1  5  7 17 71]
-----------------------

5.8:过滤操作

在Numpy中,我们一般通过布尔索引列表来过滤数组。若索引处的值为True,则该元素包含在过滤后的数组中;若索引处的值为False,则该元素将从过滤后的数组中排除。

import numpy as np

arr1=np.array([7,-3,-1,55,71,17,17])
arr2=np.array([False,True,False,True,True,False,True])

newarr=arr1[arr2] # 进行布尔索引操作【过滤】
print(newarr)
--------------------------
[-3 55 71 17]
--------------------------

过滤器的搭建

import numpy as np

arr1=np.array([7,-3,-1,55,71,17,17])
# 直接从数组创建过滤器
arr2=arr1>0 # 筛选出大于0的数
newarr=arr1[arr2] # 过滤

print(newarr)
----------------------
[ 7 55 71 17 17]
----------------------
---------------
> ```

### 5.7:去重操作

通过**unique()函数**实现去重,其返回一个由**目标数组中唯一值排序后**形成的**一维数组**。

```python
import numpy as np

arr = np.array([[7,-3,-1,5], [5,71,17,17]])
u_arr=np.unique(arr)
print(u_arr)
-----------------------
[-3 -1  5  7 17 71]
-----------------------