NumPy - 数据类型
NumPy 数据类型
NumPy 支持的数值类型比 Python 多得多。下表列出了 NumPy 中定义的各种标量数据类型。
序号 | 数据类型 &说明 |
---|---|
1 |
bool_ 以字节形式存储的布尔值(True 或 False) |
2 |
int_ 默认整数类型(与 C 语言的 long 类型相同;通常为 int64 或 int32) |
3 |
intc 与 C 语言的 int 类型相同(通常为 int32 或 int64) |
4 |
intp 用于索引的整数(与 C 语言的 ssize_t 相同;通常为 int32 或 int64) |
5 |
int8 字节 (-128 到 127) |
6 |
int16 整数 (-32768 到 32767) |
7 |
int32 整数 (-2147483648 至 2147483647) |
8 |
int64 整数 (-9223372036854775808 至 9223372036854775807) |
9 |
uint8 无符号整数(0 至 255) |
10 |
uint16 无符号整数(0 至 65535) |
11 |
uint32 无符号整数(0 至 4294967295) |
12 |
uint64 无符号整数(0 至18446744073709551615) |
13 |
float_ float64 的简写 |
14 |
float16 半精度浮点数:符号位,指数 5 位,尾数 10 位 |
15 |
float32 单精度浮点数:符号位,指数 8 位,尾数 23 位尾数 |
16 |
float64 双精度浮点数:符号位,11 位指数,52 位尾数 |
17 |
complex_ complex128 的简写 |
18 |
complex64 复数,由两个 32 位浮点数(实部和虚部)表示 |
19 |
complex128 复数,由两个 64 位浮点数(实部和虚部)表示 |
NumPy 数值类型是 dtype(数据类型)对象的实例,每个对象都具有独特的特性。可用的数据类型包括 np.bool_、np.float32 等。
数据类型对象 (dtype)
数据类型对象描述对数组对应固定内存块的解释,具体取决于以下方面:
数据类型(整数、浮点数或 Python 对象)
数据大小
字节顺序(小端或大端)
如果是结构化类型,则字段名称、每个字段的数据类型以及每个字段占用的内存块部分。
如果数据类型是子数组,则其形状和数据类型
字节顺序通过在数据类型前添加 '<' 或 '>' 前缀来决定。'<' 表示编码为小端序(最低有效位存储在最小地址中)。'>' 表示编码为大端序(最高有效位存储在最小地址中)。
使用以下语法构造 dtype 对象 -
numpy.dtype(object, align, copy)
参数如下 -
Object - 待转换为数据类型 object
Align - 如果为 true,则向字段添加填充,使其类似于 C 结构体
Copy - 复制 dtype 对象。如果为 false,则结果为对内置数据类型对象的引用
示例:使用数组标量类型
import numpy as np dt = np.dtype(np.int32) print(dt)
以下是获得的输出 -
int32
示例:使用等效字符串作为数据类型
import numpy as np dt = np.dtype('i4') print(dt)
这将产生以下结果 -
int32
示例:使用 Endian 表示法
import numpy as np dt = np.dtype('>i4') print(dt)
以下是上述代码的输出 -
>i4
示例:创建结构化数据类型
以下示例展示了结构化数据类型的用法。这里需要声明字段名称和对应的标量数据类型 -
import numpy as np dt = np.dtype([('age', np.int8)]) print(dt)
输出结果如下 -
[('age', 'i1')]
示例:将结构化数据类型应用于 ndarray
import numpy as np dt = np.dtype([('age', np.int8)]) a = np.array([(10,), (20,), (30,)], dtype=dt) print(a)
执行上述代码后,我们得到以下输出 -
[(10,) (20,) (30,)]
示例:访问结构化数据类型的字段内容
import numpy as np dt = np.dtype([('age', np.int8)]) a = np.array([(10,), (20,), (30,)], dtype=dt) print(a['age'])
生成的结果如下 -
[10 20 30]
示例:定义复杂的结构化数据类型
以下示例定义了一个名为 student 的结构化数据类型,其中包含一个字符串字段"name",一个整数字段"age"和一个浮点型字段"marks"。此数据类型应用于 ndarray 对象 -
import numpy as np student = np.dtype([('name', 'S20'), ('age', 'i1'), ('marks', 'f4')]) print(student)
我们得到如下所示的输出 -
[('name', 'S20'), ('age', 'i1'), ('marks', '<f4')])
示例:将复杂结构化数据类型应用于 ndarray
import numpy as np student = np.dtype([('name', 'S20'), ('age', 'i1'), ('marks', 'f4')]) a = np.array([('abc', 21, 50), ('xyz', 18, 75)], dtype=student) print(a)
输出如下 −
[('abc', 21, 50.0), ('xyz', 18, 75.0)]
每个内置数据类型都有一个唯一标识它的字符代码。
'b' − 布尔值
'i' − (有符号)整数
'u' − 无符号整数
'f' − 浮点数
'c' − 复数浮点数
'm' − 时间增量
'M' − 日期时间
'O' − (Python) 对象
'S', 'a' − (字节)字符串
'U' − Unicode
'V' − 原始数据 (void)
检查数组的数据类型
您可以使用 dtype 属性检查数组的数据类型。此属性返回一个 dtype 对象,该对象描述数组中元素的类型,如下所示 -
import numpy as np a = np.array([1, 2, 3]) print(a.dtype)
以下是获得的输出 -
int64
创建具有定义数据类型的数组
在 NumPy 中,您可以在创建数组时明确指定其元素的数据类型 (dtype)。
我们可以在数组创建函数(例如 np.array()、np.zeros()、np.ones() 等)中使用 dtype 参数来定义数组元素的数据类型。默认情况下,NumPy 会引用输入数据的数据类型。
示例:创建整数数组
在本例中,我们创建一个数组 a,其元素类型为 int32,这意味着每个元素都是一个 32 位整数 -
import numpy as np # 创建指定数据类型的整数数组 a = np.array([1, 2, 3], dtype=np.int32) print("数组:", a) print("数据类型:", a.dtype)
这将产生以下结果 -
数组: [1 2 3] 数据类型: int32
示例:创建整数数组
这里,我们创建一个数组 c,其元素类型为 complex64,表示 64 位复数(32 位实部和 32 位虚部)。-
import numpy as np # 创建指定 dtype 的复数数组 c = np.array([1+2j, 3+4j, 5+6j], dtype=np.complex64) print("数组:", c) print("数据类型:", c.dtype)
以下是上述代码的输出 -
数组:[1.+2.j 3.+4.j 5.+6.j] 数据类型:complex64
转换 NumPy 数组的数据类型
NumPy 提供了多种方法来转换数组的数据类型,允许您在不修改底层值的情况下更改数据的存储和处理方式 -
astype() 方法 - 这是最常用的类型转换方法。
numpy.cast() 函数 - NumPy 提供的一组函数,用于将数组转换为不同类型的类型。
就地类型转换 - 在创建数组时直接转换类型。
示例:使用"astype"方法
astype 方法创建数组的副本,并将其转换为指定类型。这是更改数组数据类型最常用的方法。
这里,我们使用 NumPy 中的 astype() 方法将一个整数数组转换为浮点数据类型 -
import numpy as np # 创建整数数组 a = np.array([1, 2, 3, 4, 5]) print("原始数组:", a) print("原始数据类型:", a.dtype) # 转换为浮点型 a_float = a.astype(np.float32) print("转换后的数组:", a_float) print("转换后的数据类型:", a_float.dtype)
得到的输出如下所示 -
原始数组:[1 2 3 4 5] 原始数据类型:int64 转换后的数组:[1. 2. 3. 4. 5.] 转换后的数据类型:float32
示例:使用"numpy.cast"函数
NumPy 还提供了将数组转换为特定类型的函数。这些函数不太常用,但在某些情况下很方便。
在本例中,我们创建一个浮点数数组,并使用 numpy.int32() 函数将其转换为整数 -
import numpy as np # 创建一个浮点数数组 d = np.array([1.1, 2.2, 3.3, 4.4, 5.5]) print("原始数组:", d) print("原始数据类型:", d.dtype) # 使用 numpy.int32 转换为整数 d_int = np.int32(d) print("转换后的数组:", d_int) print("转换后的数据类型:", d_int.dtype)
执行上述代码后,我们得到以下输出 −
原始数组:[1.1 2.2 3.3 4.4 5.5] 原始数据类型:float64 转换后的数组:[1 2 3 4 5] 转换后的数据类型:int32
示例:就地类型转换
您还可以在创建数组时指定数据类型,以避免稍后进行类型转换。
现在,我们使用 numpy.float32() 函数指定浮点数据类型来创建一个整数数组 -
import numpy as np # 创建指定数据类型的整数数组 e = np.array([1, 2, 3, 4, 5], dtype=np.float32) print("数组:", e) print("数据类型:", e.dtype)
生成的结果如下 -
数组:[1. 2. 3. 4. 5.] 数据类型:float32
如果值无法转换怎么办?
在 NumPy 中转换数据类型时,您可能会遇到无法转换为所需类型的值。这种情况通常会引发错误或导致意外行为。
让我们探讨一下无法转换值的不同场景以及如何处理它们 -
场景 1:将非数字字符串转换为数字
如果您尝试将非数字字符串转换为整数或浮点数,NumPy 将引发 ValueError,如下所示 -
import numpy as np # 创建包含非数字字符串的数组 a = np.array(['1', '2', 'three', '4', '5']) print("原始数组:", a) print("原始数据类型:", a.dtype) try: # 尝试转换为整数 a_int = a.astype(np.int32) print("转换后的数组:", a_int) print("转换后的数据类型:", a_int.dtype) except ValueError as e: print("Error:", e)
在本例中,字符串"three"无法转换为整数,导致 ValueError,如下图所示 -
原始数组:['1' '2' 'three' '4' '5'] 原始数据类型:<U5 Error: invalid literal for int() with base 10: 'three'
场景 2:转换超出范围的数字
如果您尝试转换超出目标数据类型范围的数字,NumPy 将引发 OverflowError -
import numpy as np # 创建一个包含较大浮点值的数组 b = np.array([1.1e10, 2.2e10, 3.3e10]) print("原始数组:", b) print("原始数据类型:", b.dtype) try: # 尝试转换为整数 b_int = b.astype(np.int32) print("转换后的数组:", b_int) print("转换后的数据类型:", b_int.dtype) except OverflowError as e: print("Error:", e)
此处,较大的浮点值无法转换为 int32 类型,否则会溢出 -
原始数组:[1.1e+10 2.2e+10 3.3e+10] 原始数据类型:float64 Error: OverflowError: (34, 'Numerical result out of range')
场景 3:将复数转换为实数
将复数转换为实数时,NumPy 会丢弃虚部并引发 ComplexWarning -
import numpy as np # 创建包含复数的数组 c = np.array([1+2j, 3+4j, 5+6j]) print("原始数组:", c) print("原始数据类型:", c.dtype) # 转换为浮点数,丢弃虚部 c_float = c.astype(np.float32) print("转换后的数组:", c_float) print("转换后的数据类型:", c_float.dtype)
在本例中,NumPy引发 ComplexWarning 并在转换过程中丢弃虚部 -
原始数组:[1.+2.j 3.+4.j 5.+6.j] 原始数据类型:complex128 ComplexWarning: Casting complex values to real discards the imaginary partc_float = c.astype(np.float32) 转换后的数组:[1. 3. 5.] 转换后的数据类型:float32
场景 4:处理转换错误
要处理转换错误,您可以使用错误处理技术(例如 try-except 块)来捕获和处理异常。
import numpy as np # 创建包含混合数据的数组 d = np.array(['1', '2', 'three', '4', '5']) print("原始数组:", d) print("原始数据类型:", d.dtype) def safe_convert(arr, target_type): try: return arr.astype(target_type) except ValueError as e: print("Conversion error:", e) return None # 尝试转换为整数 d_int = safe_convert(d, np.int32) if d_int is not None: print("转换后的数组:", d_int) print("转换后的数据类型:", d_int.dtype) else: print("Conversion failed.")
在此示例中,safe_convert() 函数捕获了"ValueError"并通过返回 None 并打印错误消息来处理它,如下图所示 -
原始数组:['1' '2' 'three' '4' '5'] 原始数据类型:<U5 Conversion error: invalid literal for int() with base 10: 'three' Conversion failed.
场景 5:使用"np.nan"进行无效转换
对于数值转换,可以使用 np.nan(非数字)来处理无效值。此方法在处理缺失或损坏的数据时非常有用。
import numpy as np # 创建一个包含无效条目的字符串数组 e = np.array(['1.1', '2.2', 'three', '4.4', '5.5']) print("原始数组:", e) print("原始数据类型:", e.dtype) def convert_with_nan(arr): result = [] for item in arr: try: result.append(float(item)) except ValueError: result.append(np.nan) return np.array(result) # 使用 np.nan 将无效条目转换为浮点型 e_float = convert_with_nan(e) print("转换后的数组:", e_float) print("转换后的数据类型:", e_float.dtype)
此处,无效条目被替换为 np.nan -
原始数组:['1.1' '2.2' 'three' '4.4' '5.5'] 原始数据类型:<U5 转换后的数组:[1.1 2.2 nan 4.4 5.5] 转换后的数据类型:float64
转换现有数组的数据类型
您还可以使用 view() 方法转换现有数组的数据类型,以更改数据的解释,而无需更改底层字节。
示例
此处,数据被重新解释为"float32",由于底层字节保持不变,因此导致出现意外值 -
import numpy as np # 创建整数数组 g = np.array([1, 2, 3, 4], dtype=np.int32) print("原始数组:", g) print("原始数据类型:", g.dtype) # 将数组视为 float32 g_view = g.view(np.float32) print("查看后的数组:", g_view) print("查看后的数据类型:", g_view.dtype)
以下是上述代码的输出 -
原始数组:[1 2 3 4] 原始数据类型:int32 查看后的数组:[1.4012985e-45 2.8025969e-45 4.2038954e-45 5.6051939e-45] 查看后的数据类型:float32