2、Numpy Ndarray 对象

1、番外说明

大家好,我是小P,本系列是本人对Python模块Numpy的一些学习记录,总结于此一方面方便其它初学者学习,另一方面害怕自己遗忘,希望大家喜欢。此外,对“目标检测/模型压缩/语义分割”感兴趣的小伙伴,欢迎加入QQ群 813221712 讨论交流,进群请看群公告!(可以点击如下连接直接加入!)
点击链接加入群聊【Object Detection】:https://jq.qq.com/?_wv=1027&k=5kXCXF8

2、正题

参考链接:
http://www.runoob.com/numpy/numpy-ndarray-object.html
https://cloud.tencent.com/developer/article/1106669
2.1 ndarray介绍

NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。ndarray 对象是用于存放同类型元素的多维数组。ndarray 中的每个元素在内存中都有相同存储大小的区域。

NumPy的ndarray提供了一种将同质数据块(可以是连续或跨越)解释为多维数组对象的方式。正如你之前所看到的那样,数据类型(dtype)决定了数据的解释方式,比如浮点数、整数、布尔值等。

ndarray如此强大的部分原因是所有数组对象都是数据块的一个跨度视图(strided view)。你可能想知道数组视图arr[::2,::-1]不复制任何数据的原因是什么。简单地说,ndarray不只是一块内存和一个dtype,它还有跨度信息,这使得数组能以各种步幅(step size)在内存中移动。

ndarray 内部由以下内容组成:

● 一个指向数据(内存或内存映射文件中的一块数据)的指针,这个指针能够找到存储的数组值。

● 数据类型或 dtype,描述在数组中的固定大小值的格子。numpy有一套自己的类型,如np.int8、np.float32

● 一个表示数组形状(shape)的元组,表示各维度大小的元组。如(3,2)表示3行2列的数组

● 一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要"跨过"的字节数。跨度可以是负数,这样会使数组在内存中后向移动,切片中 obj[::-1] 或 obj[:,::-1] 就是如此。

ndarray 的内部结构:
在这里插入图片描述
一个典型的(C顺序,稍后将详细讲解)3×4×5的float64(8个字节)数组,其跨度为(160,40,8),这儿跨度的计算根据数据的存储计算,数据三个维度,一共三个跨度。第一个跨度为4×5×8大小,跨一个二维矩阵平面,第二个跨度为5×8,跨一个矩阵的一行,第三个跨度为1×8,跨矩阵的一个元素

知道跨度是非常有用的,通常,跨度在一个轴上越大,沿这个轴进行计算的开销就越大。虽然NumPy用户很少会对数组的跨度信息感兴趣,但它们却是构建非复制式数组视图的重要因素。

可以通过如下代码获取数组的跨度,由此可见知道跨度的意义:

A=np.ones((3,4,5),dtype=np.float64)

A.shape
Out[13]: (3, 4, 5)

A
Out[14]: 
array([[[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]]])

A.strides
Out[15]: (160, 40, 8)

由上述可知,由第一维跨度160除以第二维跨度,可以知道矩阵的行数,同理,第二维除以第三维跨度可以知道矩阵的列数,这对于C语言中数据按行存储是非常关键的信息。

NumPy数据类型体系

你可能偶尔需要检查数组中所包含的是否是整数、浮点数、字符串或Python对象。因为浮点数的种类很多(从float16到float128),判断dtype是否属于某个大类的工作非常繁琐。幸运的是,dtype都有一个超类(比如np.integer和np.floating),它们可以跟np.issubdtype函数结合使用:

In [12]: ints = np.ones(10, dtype=np.uint16)

In [13]: floats = np.ones(10, dtype=np.float32)

In [14]: np.issubdtype(ints.dtype, np.integer)
Out[14]: True

In [15]: np.issubdtype(floats.dtype, np.floating)
Out[15]: True

其中,issubdtype函数用来判断某类是否是另一个类的子类

调用dtype的mro方法即可查看其所有的父类:

In [16]: np.float64.mro()
Out[16]:
[numpy.float64,
 numpy.floating,
 numpy.inexact,
 numpy.number,
 numpy.generic,
 float,
 object]

然后得到:

In [17]: np.issubdtype(ints.dtype, np.number)
Out[17]: True

其中,mro()用于获取某个类型的继承链,详细查询参考:https://study.163.com/course/courseLearn.htm?courseId=1005985001#/learn/video?lessonId=1053350157&courseId=1005985001

大部分NumPy用户完全不需要了解这些知识,但是这些知识偶尔还是能派上用场的。下图说明了dtype体系以及父子类关系。
在这里插入图片描述

2.2 ndarray创建数组

创建一个 ndarray 只需调用 NumPy 的 array 函数即可:

numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)

参数说明:
在这里插入图片描述
实例
接下来可以通过以下实例帮助我们更好的理解。

实例 1
生成一个一维的数组

import numpy as np 
a = np.array([1,2,3])  
print (a)

输出结果如下:

array( [1, 2, 3])

实例 2
生成一个二维数组

import numpy as np 
a = np.array([[1,  2],  [3,  4]])  
print (a)

输出结果如下:

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

实例 3
通过ndmin参数指定生成数组的最小维度

import numpy as np 
a = np.array([1, 2, 3, 4, 5], ndmin =  2)  
print (a)

输出如下:

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

注意,当指定ndmin=2时,则表示生成的数组维度为2,即a的维度为(1,5),默认前向扩展一维
实例 4
使用dtype 参数更改数据类型

import numpy as np 
a = np.array([1,  2,  3], dtype = complex)  
print (a)

输出结果如下:

array([1.+0.j, 2.+0.j, 3.+0.j])

这儿的数据类型为复数类型

ndarray 对象由计算机内存的连续一维部分组成,并结合索引模式,将每个元素映射到内存块中的一个位置。内存块以行顺序(C样式)或列顺序(FORTRAN或MatLab风格,即前述的F样式)来保存元素。

NumPy(Numerical Python)是 Python 中用于科学计算的核心库,它提供了高性能的多维数组对象 `ndarray`(N-dimensional array),以及对这些数组进行操作的工具。`ndarray` 是 NumPy 的核心数据结构,它是一个同构的、固定大小的多维容器,用于存储相同类型的数据。 --- ### 1. Ndarray 对象的基本特点 - **同质性**:`ndarray` 中的所有元素必须是相同的数据类型(如 `int32`, `float64` 等),这使得内存布局连续,运算高效。 - **多维性**:可以是一维(向量)、二维(矩阵)、三维甚至更高维度的数组。 - **固定大小**:创建后大小固定(修改形状或大小会创建新对象)。 - **高效的向量化操作**:支持广播机制和逐元素操作,无需显式循环,性能远高于原生 Python 列表。 --- ### 2. 创建 ndarray 的常用方法 ```python import numpy as np # 从列表创建 arr1 = np.array([1, 2, 3]) # 一维数组 arr2 = np.array([[1, 2], [3, 4]]) # 二维数组 # 特殊数组 arr_zeros = np.zeros((2, 3)) # 全0数组 arr_ones = np.ones((2, 2)) # 全1数组 arr_empty = np.empty((2, 2)) # 未初始化的数组(值随机) arr_range = np.arange(0, 10, 2) # 类似 range,生成 [0, 2, 4, 6, 8] arr_linspace = np.linspace(0, 1, 5) # 在 [0,1] 间均匀生成 5 个数 # 指定数据类型 arr_float = np.array([1, 2, 3], dtype=np.float64) ``` --- ### 3. ndarray 的重要属性 ```python arr = np.array([[1, 2, 3], [4, 5, 6]]) print(arr.ndim) # 维度数:2 print(arr.shape) # 形状:(2, 3) print(arr.size) # 元素总数:6 print(arr.dtype) # 数据类型:int64 print(arr.itemsize) # 每个元素字节数:8(int64) print(arr.nbytes) # 总字节数:48(6 * 8) ``` --- ### 4. 数组索引与切片 ```python arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 索引 print(arr[0, 1]) # 2 # 切片 print(arr[0:2, 1:3]) # [[2, 3], [5, 6]] # 布尔索引 print(arr[arr > 5]) # [6 7 8 9] # 花式索引(指定索引列表) print(arr[[0, 2], [1, 2]]) # [2, 9] ``` --- ### 5. 数组操作 ```python a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) # 向量化运算(逐元素) print(a + b) # [5 7 9] print(a * 2) # [2 4 6] print(a ** 2) # [1 4 9] # 矩阵乘法 A = np.array([[1, 2], [3, 4]]) B = np.array([[5, 6], [7, 8]]) print(A.dot(B)) # 矩阵乘法 print(A @ B) # 同上,推荐写法 # 广播机制 c = np.array([[1, 2], [3, 4]]) d = np.array([10, 20]) print(c + d) # [[11 22], [13 24]] ``` --- ### 6. 改变形状与重塑 ```python arr = np.arange(6) reshaped = arr.reshape((2, 3)) # 变为 2x3 flattened = reshaped.flatten() # 展平为一维 transposed = reshaped.T # 转置 print(reshaped) print(flattened) print(transposed) ``` --- ### 7. 为什么使用 ndarray 而不是 Python 列表? | 对比项 | Python 列表 | NumPy ndarray | |------------------|-------------------------------|------------------------------------| | 数据类型 | 异构(可混合类型) | 同构(固定类型) | | 存储效率 | 低(每个元素是对象指针) | 高(连续内存块) | | 运算速度 | 慢(需解释器循环) | 快(C语言实现,SIMD优化) | | 向量化操作 | 不支持 | 支持(+、-、*、/ 等直接作用于整体)| | 广播机制 | 不支持 | 支持 | | 内存占用 | 大 | 小 | --- ### 8. 底层原理简述 `ndarray` 是一个指向内存块的结构体,包含: - 数据指针(指向实际数据) - 形状(shape) - 步长(strides):跳到下一个维度所需字节数 - 数据类型(dtype) - 标志位(如是否可写、是否连续等) 这种设计使得视图(view)操作非常高效(如切片不复制数据)。 --- ### 总结 `ndarray` 是高性能数值计算的基础,它的设计兼顾了灵活性和效率,广泛应用于数据科学、机器学习、图像处理等领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值