2.3 ndarray 的数据类型 (dtype) 详解


文档摘要

2.3 ndarray 的数据类型 (dtype) 详解 2.3 ndarray 的数据类型 (dtype) 详解 (N-dimensional array) 是 NumPy 库的核心数据结构,用于存储同类型数据的多维数组。理解 的数据类型 ( ) 对于高效使用 NumPy 至关重要。 决定了数组中元素的类型,以及它们在内存中的存储方式。 2.3.1 的重要性 影响着: 内存占用: 不同的数据类型占用不同的内存空间。选择合适的 可以有效减少内存消耗,尤其是在处理大型数据集时。 计算性能: NumPy 针对不同的 进行了优化。选择与数据匹配的 可以提升计算速度。 数据精度: 决定了数据的精度范围。例如,使用 相比 可以节省内存,但精度会降低。

2.3 ndarray 的数据类型 (dtype) 详解

2.3 ndarray 的数据类型 (dtype) 详解

ndarray (N-dimensional array) 是 NumPy 库的核心数据结构,用于存储同类型数据的多维数组。理解 ndarray 的数据类型 (dtype) 对于高效使用 NumPy 至关重要。dtype 决定了数组中元素的类型,以及它们在内存中的存储方式。

2.3.1 dtype 的重要性

dtype 影响着:

  • 内存占用: 不同的数据类型占用不同的内存空间。选择合适的 dtype 可以有效减少内存消耗,尤其是在处理大型数据集时。

  • 计算性能: NumPy 针对不同的 dtype 进行了优化。选择与数据匹配的 dtype 可以提升计算速度。

  • 数据精度: dtype 决定了数据的精度范围。例如,使用 float32 相比 float64 可以节省内存,但精度会降低。

  • 数据兼容性: 与其他库(如 Pandas、SciPy)交互时,dtype 的一致性非常重要,可以避免数据类型转换带来的性能损失和潜在错误。

2.3.2 NumPy 中常见的 dtype

NumPy 提供了丰富的数据类型,可以满足各种数值和非数值数据的存储需求。 常见的dtype包括:

数据类型 描述 别名
bool_ 布尔类型,存储 TrueFalse bool
int_ 默认的整数类型,通常是 int64int32 (取决于系统)。 int
int8 8 位整数,范围为 -128 到 127。
int16 16 位整数,范围为 -32768 到 32767。
int32 32 位整数,范围为 -2147483648 到 2147483647。
int64 64 位整数,范围为 -9223372036854775808 到 9223372036854775807。
uint8 8 位无符号整数,范围为 0 到 255。
uint16 16 位无符号整数,范围为 0 到 65535。
uint32 32 位无符号整数,范围为 0 到 4294967295。
uint64 64 位无符号整数,范围为 0 到 18446744073709551615。
float_ 默认的浮点数类型,通常是 float64 float
float16 半精度浮点数。 half
float32 单精度浮点数。 single
float64 双精度浮点数。 double
complex_ 默认的复数类型,通常是 complex128 complex
complex64 由两个 32 位浮点数表示的复数。
complex128 由两个 64 位浮点数表示的复数。
object_ Python 对象类型,可以存储任意 Python 对象。 object
string_ 固定长度字符串类型。 str
unicode_ Unicode 类型。
datetime64 用于存储日期和时间。
timedelta64 用于表示时间间隔。

2.3.3 创建指定 dtypendarray

在创建 ndarray 时,可以通过 dtype 参数显式指定数据类型。

import numpy as np # 创建 int32 类型的数组 arr_int32 = np.array([1, 2, 3], dtype=np.int32) print(arr_int32.dtype) # 输出:int32 # 创建 float64 类型的数组 arr_float64 = np.array([1.0, 2.0, 3.0], dtype=np.float64) print(arr_float64.dtype) # 输出:float64 # 创建 bool 类型的数组 arr_bool = np.array([0, 1, 0], dtype=bool) print(arr_bool.dtype) # 输出:bool print(arr_bool) # 输出:[False True False] # 创建字符串类型的数组 arr_str = np.array([1, 2, 3], dtype=np.string_) print(arr_str.dtype) print(arr_str) # [b'1' b'2' b'3'] arr_unicode = np.array(['你好', '世界'], dtype=np.unicode_) print(arr_unicode.dtype) print(arr_unicode) # ['你好' '世界']

2.3.4 ndarraydtype 属性

每个 ndarray 对象都有一个 dtype 属性,用于访问其数据类型。

import numpy as np arr = np.array([1, 2, 3]) print(arr.dtype) # 输出:int64 (或 int32,取决于系统) arr_float = np.array([1.0, 2.0, 3.0]) print(arr_float.dtype) # float64

2.3.5 数据类型转换

可以使用 astype() 方法将 ndarray 的数据类型转换为另一种类型。

import numpy as np arr = np.array([1, 2, 3], dtype=np.int32) print(arr.dtype) # 输出:int32 arr_float = arr.astype(np.float64) print(arr_float.dtype) # 输出:float64 print(arr_float) # [1. 2. 3.] arr_str = arr.astype(np.string_) print(arr_str.dtype) print(arr_str) # [b'1' b'2' b'3'] arr_bool = arr.astype(np.bool_) print(arr_bool.dtype) print(arr_bool) # [ True True True] arr_uint8 = arr.astype(np.uint8) print(arr_uint8.dtype) print(arr_uint8) # [1 2 3]

注意: 数据类型转换可能会导致数据丢失或精度降低。例如,将浮点数转换为整数会截断小数部分。

import numpy as np arr_float = np.array([1.5, 2.7, 3.9]) arr_int = arr_float.astype(np.int32) print(arr_int) # 输出:[1 2 3] (小数部分被截断)

2.3.6 dtype 的结构化表示

dtype 还可以用于定义结构化数组,其中每个元素可以包含多个字段,每个字段可以有不同的数据类型。

import numpy as np # 定义一个结构化 dtype dt = np.dtype([('name', np.unicode_, 16), ('age', np.int32), ('height', np.float64)]) # 创建一个结构化数组 people = np.array([('Alice', 25, 1.75), ('Bob', 30, 1.80)], dtype=dt) print(people) # 输出: # [('Alice', 25, 1.75) ('Bob', 30, 1.8 )] print(people['name']) # 输出:['Alice' 'Bob'] print(people['age']) # 输出:[25 30]

2.3.7 字节序 (Endianness)

dtype 还可以指定字节序,用于在内存中存储多字节数据的顺序。常见的字节序有:

  • 大端序 (Big-endian): 高位字节存储在低地址处。

  • 小端序 (Little-endian): 低位字节存储在低地址处。

NumPy 默认使用系统的字节序。可以使用 > (大端序) 或 < (小端序) 前缀来显式指定字节序。

import numpy as np # 创建大端序的 int32 数组 arr_big_endian = np.array([1, 2, 3], dtype='>i4') print(arr_big_endian.dtype) # 输出:>i4 # 创建小端序的 int32 数组 arr_little_endian = np.array([1, 2, 3], dtype='<i4') print(arr_little_endian.dtype) # 输出:<i4

通常情况下,不需要显式指定字节序,除非需要与其他系统或数据格式进行交互。

2.3.8 Graph TD 图示

下面使用 mermaid 绘制一个简单的 dtype 关系图:

2.3.9 代码实践

案例 1:优化内存占用

假设需要存储 100 万个 0 到 255 之间的整数。如果使用默认的 int64 类型,需要 8MB 的内存。但如果使用 uint8 类型,只需要 1MB 的内存。

import numpy as np # 使用 int64 arr_int64 = np.random.randint(0, 256, size=1000000, dtype=np.int64) print(f"int64 数组占用内存:{arr_int64.nbytes / 1024 / 1024:.2f} MB") # 使用 uint8 arr_uint8 = np.random.randint(0, 256, size=1000000, dtype=np.uint8) print(f"uint8 数组占用内存:{arr_uint8.nbytes / 1024 / 1024:.2f} MB")

案例 2:提升计算速度

对于某些计算,使用较低精度的数据类型可以提升计算速度。例如,在深度学习中,经常使用 float32 代替 float64

import numpy as np import time # 创建两个大型 float64 数组 a = np.random.rand(1000, 1000).astype(np.float64) b = np.random.rand(1000, 1000).astype(np.float64) # 计算 float64 数组的乘积 start_time = time.time() c_float64 = np.dot(a, b) end_time = time.time() print(f"float64 乘法耗时:{end_time - start_time:.4f} 秒") # 创建两个大型 float32 数组 a_float32 = a.astype(np.float32) b_float32 = b.astype(np.float32) # 计算 float32 数组的乘积 start_time = time.time() c_float32 = np.dot(a_float32, b_float32) end_time = time.time() print(f"float32 乘法耗时:{end_time - start_time:.4f} 秒")

案例 3:处理缺失数据

可以使用 np.nan (Not a Number) 表示浮点数数组中的缺失值。

import numpy as np arr = np.array([1.0, 2.0, np.nan, 4.0], dtype=np.float64) print(arr) # 输出:[ 1. 2. nan 4.] # 使用 np.isnan() 检测缺失值 print(np.isnan(arr)) # 输出:[False False True False] # 替换缺失值为 0 arr[np.isnan(arr)] = 0 print(arr) # 输出:[1. 2. 0. 4.]

2.3.10 总结

ndarraydtype 是 NumPy 中一个非常重要的概念。理解 dtype 的各种类型、创建方式、转换方法以及字节序等特性,可以帮助我们编写更高效、更健壮的 NumPy 代码。在实际应用中,应该根据数据的特点和计算需求,选择合适的 dtype,以优化内存占用、提升计算性能,并确保数据的准确性和兼容性。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U