数据类型
前面说过,ndarray
对象中存储的元素其类型都是相同的,而且通常是数值型的元素。与原生Python
相比,NumPy
提供了更多种类、更加精确的数值类型,基本上是和C
语言中的数值类型是相对应的,具体可以参考 这里。说到C
语言中的数值类型,我们就应该知道,在不同字长的机器上,有些相同的类型表示的数据范围是不同的,这是一个比较头疼的问题,在NumPy
中,也提供了固定大小、与平台无关的数值类型。
比较常用的5种数值类型有:布尔型(bool),整型(int),无符号整型(uint),浮点型(float)和复数类型(complex)。不同类型的数值在内存中占用的空间是不一样的,有些类型,即使相同,它们不同机器上占用的内存空间也会有差别。
类型转换
这些类型可以直接作为函数将原生Python
的数值类型转换为NumPy
中定义的数值类型。
# 1. 直接对数值进行转换
n = 1.23
print(type(n)) # <class 'float'>
import numpy as np
n = numpy.float32(n)
print(type(n)) # <class 'numpy.float32'>
# 2. 对 Python 序列进行转换
# 数据类型发生了转换 [list --> ndarray]
# 数值类型也发生了转换 [int --> int32 ]
v = [1, 2, 3]
np_v = np.int32(v)
print(type(np_v)) # <class 'numpy.ndarray'>
print(repr(np_v)) # array([1, 2, 3], dtype=int32)
# 3. 直接对数组对象进行转换
v = np.array([1, 2])
vf = np.float32(v)
print(repr(v), repr(vf)) # array([1, 2]) array([1., 2.], dtype=float32)
可以直接在构建NumPy
数组的过程中用关键字参数的形式进行指明。
import numpy as np
v = np.array([1, 2, 3], dtype=np.int32)
print(type(v), repr(v)) # <class 'numpy.ndarray'> array([1, 2, 3], dtype=int32)
使用数组对象的astype()
方法,对数组的数值类型进行转换。
import numpy as np
v = np.array([1, 2, 3])
fv = v.astype(np.double)
print(repr(fv)) # array([1., 2., 3.]),数字后带一个小数点,作一个提示,表示浮点类型
溢出问题
在原生Python
中,可能并不需要担心数据的溢出问题,因为与静态语言C
不同,Python
数据大小是可以动态增长的。在NumPy
中,每种数值类型是固定大小的,数值过大会出现溢出的问题。
# 计算 100 的 4 次方
import numpy as np
result_1 = np.power(100, 4) # 默认是和我机器字长一致
result_2 = np.power(100, 4, dtype=np.int16)
print(result_1, result_2) # 100000000 -7936
print(type(result_1), type(result_2)) # <class 'numpy.int64'> <class 'numpy.int16'>
所以,在使用NumPy
进行科学计算时,首先要对数据的量级有一个了解,便于选择合适的类型来进行数据存储。使用numpy.iinfo()
和numpy.finfo()
可以分别确定整数数值类型和浮点数数值类型的表示范围。
import numpy as np
print(np.iinfo(np.int32))
# Machine parameters for int32
# ---------------------------------------------------------------
# min = -2147483648
# max = 2147483647
# ---------------------------------------------------------------
print(np.finfo(np.float32))
# Machine parameters for float32
# ---------------------------------------------------------------
# precision = 6 resolution = 1.0000000e-06
# machep = -23 eps = 1.1920929e-07
# negep = -24 epsneg = 5.9604645e-08
# minexp = -126 tiny = 1.1754944e-38
# maxexp = 128 max = 3.4028235e+38
# nexp = 8 min = -max
# ---------------------------------------------------------------
NumPy数组的创建
从原生Python类型转化
一般是通过Python
的序列类型(list,tuple等)进行转化。使用函数numpy.array()
,更详细的转换参数需求可以参考 这里 。
import numpy as np
v = np.array([1, 2, 3])
print(repr(v)) # array([1, 2, 3])
v = np.array("abcd")
print(repr(v)) # array('abcd', dtype='<U4')
# 精度自动提升
v = np.array((1, 2.3, 0))
print(repr(v)) # array([1. , 2.3, 0. ])
# 指定转换后的数值类型
v = np.array([2, 3], dtype=np.int16)
print(repr(v)) # array([2, 3], dtype=int16)
# 转化成多维数组
v = np.array([[1, 2], [4, 5]])
print(repr(v))
# array([[1, 2],
# [4, 5]])
# ** 每一维的数据元素个数要对其 **
v = np.array([[1, 2], [3, 4, 5]])
print(repr(v)) # array([list([1, 2]), list([3, 4, 5])], dtype=object)
使用内置的函数直接生成
通过一些内置的函数,可以快速生成一些特殊形式的NumPy
数组。
numpy.zeros()
生成给定「尺寸」的数组,元素全为0
,默认的存储类型是float
。
import numpy as np
v = np.zeros(2)
print(repr(v)) # array([0., 0.])
v = np.zeros((2, 3), dtype=np.int16)
print(repr(v))
# array([[0, 0, 0],
# [0, 0, 0]], dtype=int16)
numpy.empty()
生成给定「尺寸」的数组,元素全未初始化,因为数值类型与C
一致,所以未初始化的数据值是随机的,默认的类型是float
。
import numpy as np
v = np.empty((2, 2))
print(repr(v))
# array([[1.40735731e-311, 1.40736975e-311],
# [8.61672470e-315, 8.61672486e-315]])
v = np.array((2, 2), dtype=np.int16)
print(repr(v))
# array([[ 2678, 13056],
# [ 54, 0]], dtype=int16)
numpy.ones()
生成给定「尺寸」的数组,元素全为 1 ,默认数值类型是numpy.float64
import numpy as np
v = np.ones(3)
print(repr(v)) # array([1., 1., 1.])
v = np.ones((2, 2), dtype=int)
print(repr(v))
# array([[1, 1],
# [1, 1]])
numpy.full()
生成给定「尺寸」,给定「元素」的数组,数组的元素都相同,存储类型由给定元素决定。
import numpy as np
v = np.full(3, 666)
print(repr(v)) # array([666, 666, 666])
numpy.arange()
numpy.arange([start,]stop, [step,]dtype=None)
生成给定范围和步长内的一维数组,步长可以是浮点数,数据类型根据范围和步长自动推断。
import numpy as np
v = np.arange(3)
print(repr(v)) # array([0, 1, 2])
v = np.arange(5, 2, -1)
print(repr(v)) # array([5, 4, 3])
v = np.arrange(1, 2, 0.3)
print(repr(v)) # array([1. , 1.3, 1.6, 1.9])
numpy.linspace()
通过给定的范围和元素个数来生成一维数组,与arange()
相比,它生成的一维数组首位是可以确定的,步长通过计算来确定,而且这个函数默认是包括终止元素的。
import numpy as np
v = np.linspace(1, 2, 4)
print(repr(v)) # array([1. , 1.33333333, 1.66666667, 2. ])
v = np.linspace(1, 2, 4, endpoint=False) # 不包括终止位置 2
print(repr(v)) # array([1. , 1.25, 1.5 , 1.75])