除了在构建 ndarray 对象时指定数据类型,我们还可以在完成数据构建后使用 astype 来修改数据类型。关于 Numpy 的数据类型介绍可以查看:
NumPy 的数据类型
。
# astype 语法
ndarray.astype(dtype, order='K', casting='unsafe',
subok=True, copy=True)
其中参数有:
dtype: str or dtype(dtype 对象)
将数组强制转换为的类型代码或数据类型
order: {‘C’, ‘F’, ‘A’, ‘K’}, optional
控制结果的内存布局顺序。
- “C”表示 C 顺序
- “F” 表示 Fortran 顺序
- “A”表示“F”顺序(如果所有数组都是Fortran连续的),否则是 “C” 顺序
- “K”表示尽可能接近数组元素在内存中出现的顺序。默认值为“K”。
- casting: {‘no’, ‘equiv’, ‘safe’, ‘same_kind’, ‘unsafe’}, optional
控制可能发生的数据转换类型,,默认为 “unsafe” 以实现向后兼容性。
- ‘no’ 数据类型根本不应该被强制转换
- ‘equiv’ 只允许更改字节顺序
- ‘safe’ 只允许保留值的强制转换。
- ‘same_kind’ 只允许安全强制转换或类内强制转换,如 float64 到 float32
- ‘unsafe’ 可以进行任何数据转换
- subok: bool, optional
如果为True,则传递子类(默认),否则返回的数组将强制为基类数组
- copy: bool, optional
默认情况下,astype 总是返回新分配的数组,如果设置为 false,并且满足了 dtype、order 和 subok 要求,则返回输入数组而不是副本
- arr_t: ndarray
除非 copy 为 False 并且满足返回输入数组的其他条件(请参见 copy 输入参数的描述),否则 arr_t 是与输入数组相同形状的新数组,其类型为 dtype,由 dtype 指定的顺序为 order。
- ComplexWarning(复数警告)
当从 complex 转换为 float 或 int 时,为了避免这种情况,应该使用 avoid。一个应使用的方法 a.real.astype(type)。
以下是 NumPy 近期版本关于此方法的变化:
- 在版本 1.17.0 中进行了更改:在简单数据类型和结构化数据类型之间转换只能用于“不安全”转换;允许向多个字段强制转换,但不允许从多个字段强制转换。
- 在版本 1.9.0 中更改:在“安全”强制转换模式下从数字类型强制转换为字符串类型需要字符串数据类型长度足够长,以存储转换的最大 integer/float 值。
常用的方法:
x = np.array([1, 2, 3.4])
# array([1. , 2. , 3.4])
x.astype(int)
# array([1, 2, 3])
x.dtype # dtype('float64')
# 理解部分内容转换
a = np.array([[1,2,3],[4,5,6]])
a[:,1]
# array([2, 5])
a[:,1].astype('str') # 转换后生成此副本
# array(['2', '5'], dtype='<U21')
a.dtype # 原来的数组没有改变
# dtype('int64')
# 表达式转换为 int 生成布尔数组(0/1)
(arr > 0.5).astype(int)
# 构造一个时间表达数据
arr = [2020, 12, 0.6552562894775783]
custom_type = np.dtype([
('YEAR',np.uint16),
('DOY', np.uint16),
('REF',np.float16)
d = np.array([tuple(arr)], custom_type)
array([(2020, 364, 0.6553)],
dtype=[('YEAR', '<u2'), ('DOY', '<u2'), ('REF', '<f2')])
d['YEAR'] # array([2020], dtype=uint16)
类型辅助功能
以下为 numpy 针对 dtype 的一些判定方法,可以协助我们在类型转换时高效完成工作。
最小标题类型 np.min_scalar_type
用 numpy.min_scalar_type(a)
对于标量 a,返回大小最小的数据类型,以及可以保存其值的最小标量类型。对于非标量数组 a,返回未修改的向量的数据类型。浮点值不会降级为整数,复数值也不会降级为浮点。
np.min_scalar_type(10)
# dtype('uint8')
np.min_scalar_type(-260)
# dtype('int16')
np.min_scalar_type(3.1)
# dtype('float16')
np.min_scalar_type(1e50)
# dtype('float64')
np.min_scalar_type(np.arange(4,dtype='f8'))
# dtype('float64')
类型转换检测 np.can_cast
numpy.can_cast(from_, to, casting='safe')
如果根据转换规则可以在数据类型之间进行转换,则返回True。如果 from 是标量或数组标量,如果标量值可以在不溢出或截断为整数的情况下强制转换,则也返回 True。
np.can_cast(np.float64,np.float32)
# False
np.can_cast(np.float32,np.float64)
# True
# 基本示例
np.can_cast(np.int32, np.int64)
# True
np.can_cast(np.float64, complex)
# True
np.can_cast(complex, float)
# False
np.can_cast('i8', 'f8')
# True
np.can_cast('i8', 'f4')
# False
np.can_cast('i4', 'S4')
# False
# 转换标量
np.can_cast(100, 'i1')
# True
np.can_cast(150, 'i1')
# False
np.can_cast(150, 'u1')
# True
np.can_cast(3.5e100, np.float32)
# False
np.can_cast(1000.0, np.float32)
# True
# 数组标量检查值,数组不检查
np.can_cast(np.array(1000.0), np.float32)
# True
np.can_cast(np.array([1000.0]), np.float32)
# False
# 使用转换规则
np.can_cast('i8', 'i8', 'no')
# True
np.can_cast('<i8', '>i8', 'no')
# False
np.can_cast('<i8', '>i8', 'equiv')
# True
np.can_cast('<i4', '>i8', 'equiv')
# False
np.can_cast('<i4', '>i8', 'safe')
# True
np.can_cast('<i8', '>i4', 'safe')
# False
np.can_cast('<i8', '>i4', 'same_kind')
np.can_cast('<i8', '>u4', 'same_kind')
# False
np.can_cast('<i8', '>u4', 'unsafe')
# True
标量类型检测 numpy.obj2sctype
numpy.obj2sctype(rep, default=None)
返回对象的标量 dtype 或与 NumPy 和 Python 等效类型。
np.obj2sctype(np.int32)
# <class 'numpy.int32'>
np.obj2sctype(np.array([1., 2.]))
# <class 'numpy.float64'>
np.obj2sctype(np.array([1.j]))
# <class 'numpy.complex128'>
np.obj2sctype(dict)
# <class 'numpy.object_'>
np.obj2sctype('string')
np.obj2sctype(1, default=list)
# <class 'list'>
通用类型 numpy.common_type
numpy.common_type(*arrays)
返回输入数组通用的标量类型。即使所有数组都是整数数组,返回类型也始终是不精确(即浮点)标量类型。如果其中一个输入是整数数组,则返回的最小精度类型是 64 位浮点数据类型。
除了 int64 和 uint64 之外的所有输入数组都可以安全地转换为返回的数据类型,而不会丢失信息。
np.common_type(np.arange(2, dtype=np.float32))
# <class 'numpy.float32'>
np.common_type(np.arange(2, dtype=np.float32), np.arange(2))
# <class 'numpy.float64'>
np.common_type(np.arange(4), np.array([45, 6.j]), np.array([45.0]))
# <class 'numpy.complex128'>
最小安全类型推定 np.promote_types
numpy.promote_types(type1, type2)
返回具有最小大小和最小标量类型的数据类型,type1 和 type2 都可以安全地转换到该类型。返回的数据类型总是按本机字节顺序。此函数是对称(symmetric)的,但很少是关联( rarely associative)的。
np.promote_types('f4', 'f8')
# dtype('float64')
np.promote_types('i8', 'f4')
# dtype('float64')
np.promote_types('>i8', '<c8')
# dtype('complex128')
np.promote_types('i4', 'S8')
# dtype('S11')
# 非关联(non-associative)案例示例
p = np.promote_types
p('S', p('i1', 'u1'))
# dtype('S6')
p(p('S', 'i1'), 'u1')
# dtype('S4')
引用其他数组类型 numpy.result_type
使用 numpy.result_type
可以实现引用其他已有数组类型的目的,详见npresult_type 介绍。
a = np.arange(50.)
a.dtype # dtype('float64')
# 使用 a 的数据类型
b.astype(np.result_type(a)).dtype # dtype('float64')
b = np.arange(50, dtype=np.result_type(a))
b.dtype # dtype('float64')
内存共享检测 np.may_share_memory
判断是否共享内存。
a = np.ones(3, dtype=float)
# array([ 1., 1., 1.])
b = a.astype(int)
# # array([1, 1, 1])
np.may_share_memory(a, b)
# False
c = a.astype(float)
np.may_share_memory(a, c)
# False
另外还可以用其他方法: