数据类型

前面说过,ndarray对象中存储的元素其类型都是相同的,而且通常是数值型的元素。与原生Python相比,NumPy提供了更多种类、更加精确的数值类型,基本上是和C语言中的数值类型是相对应的,具体可以参考 这里。说到C语言中的数值类型,我们就应该知道,在不同字长的机器上,有些相同的类型表示的数据范围是不同的,这是一个比较头疼的问题,在NumPy中,也提供了固定大小、与平台无关的数值类型。

比较常用的5种数值类型有:布尔型(bool),整型(int),无符号整型(uint),浮点型(float)和复数类型(complex)。不同类型的数值在内存中占用的空间是不一样的,有些类型,即使相同,它们不同机器上占用的内存空间也会有差别。

类型转换

这些类型可以直接作为函数将原生Python的数值类型转换为NumPy中定义的数值类型。

  1. # 1. 直接对数值进行转换
  2. n = 1.23
  3. print(type(n)) # <class 'float'>
  4. import numpy as np
  5. n = numpy.float32(n)
  6. print(type(n)) # <class 'numpy.float32'>
  7. # 2. 对 Python 序列进行转换
  8. # 数据类型发生了转换 [list --> ndarray]
  9. # 数值类型也发生了转换 [int --> int32 ]
  10. v = [1, 2, 3]
  11. np_v = np.int32(v)
  12. print(type(np_v)) # <class 'numpy.ndarray'>
  13. print(repr(np_v)) # array([1, 2, 3], dtype=int32)
  14. # 3. 直接对数组对象进行转换
  15. v = np.array([1, 2])
  16. vf = np.float32(v)
  17. print(repr(v), repr(vf)) # array([1, 2]) array([1., 2.], dtype=float32)

可以直接在构建NumPy数组的过程中用关键字参数的形式进行指明。

  1. import numpy as np
  2. v = np.array([1, 2, 3], dtype=np.int32)
  3. print(type(v), repr(v)) # <class 'numpy.ndarray'> array([1, 2, 3], dtype=int32)

使用数组对象的astype()方法,对数组的数值类型进行转换。

  1. import numpy as np
  2. v = np.array([1, 2, 3])
  3. fv = v.astype(np.double)
  4. print(repr(fv)) # array([1., 2., 3.]),数字后带一个小数点,作一个提示,表示浮点类型

溢出问题

在原生Python中,可能并不需要担心数据的溢出问题,因为与静态语言C不同,Python数据大小是可以动态增长的。在NumPy中,每种数值类型是固定大小的,数值过大会出现溢出的问题。

  1. # 计算 100 的 4 次方
  2. import numpy as np
  3. result_1 = np.power(100, 4) # 默认是和我机器字长一致
  4. result_2 = np.power(100, 4, dtype=np.int16)
  5. print(result_1, result_2) # 100000000 -7936
  6. print(type(result_1), type(result_2)) # <class 'numpy.int64'> <class 'numpy.int16'>

所以,在使用NumPy进行科学计算时,首先要对数据的量级有一个了解,便于选择合适的类型来进行数据存储。使用numpy.iinfo()numpy.finfo()可以分别确定整数数值类型浮点数数值类型的表示范围。

  1. import numpy as np
  2. print(np.iinfo(np.int32))
  3. # Machine parameters for int32
  4. # ---------------------------------------------------------------
  5. # min = -2147483648
  6. # max = 2147483647
  7. # ---------------------------------------------------------------
  8. print(np.finfo(np.float32))
  9. # Machine parameters for float32
  10. # ---------------------------------------------------------------
  11. # precision = 6 resolution = 1.0000000e-06
  12. # machep = -23 eps = 1.1920929e-07
  13. # negep = -24 epsneg = 5.9604645e-08
  14. # minexp = -126 tiny = 1.1754944e-38
  15. # maxexp = 128 max = 3.4028235e+38
  16. # nexp = 8 min = -max
  17. # ---------------------------------------------------------------

NumPy数组的创建

从原生Python类型转化

一般是通过Python的序列类型(list,tuple等)进行转化。使用函数numpy.array(),更详细的转换参数需求可以参考 这里

  1. import numpy as np
  2. v = np.array([1, 2, 3])
  3. print(repr(v)) # array([1, 2, 3])
  4. v = np.array("abcd")
  5. print(repr(v)) # array('abcd', dtype='<U4')
  6. # 精度自动提升
  7. v = np.array((1, 2.3, 0))
  8. print(repr(v)) # array([1. , 2.3, 0. ])
  9. # 指定转换后的数值类型
  10. v = np.array([2, 3], dtype=np.int16)
  11. print(repr(v)) # array([2, 3], dtype=int16)
  12. # 转化成多维数组
  13. v = np.array([[1, 2], [4, 5]])
  14. print(repr(v))
  15. # array([[1, 2],
  16. # [4, 5]])
  17. # ** 每一维的数据元素个数要对其 **
  18. v = np.array([[1, 2], [3, 4, 5]])
  19. print(repr(v)) # array([list([1, 2]), list([3, 4, 5])], dtype=object)

使用内置的函数直接生成

通过一些内置的函数,可以快速生成一些特殊形式的NumPy数组。

numpy.zeros()

生成给定「尺寸」的数组,元素全为0,默认的存储类型是float

  1. import numpy as np
  2. v = np.zeros(2)
  3. print(repr(v)) # array([0., 0.])
  4. v = np.zeros((2, 3), dtype=np.int16)
  5. print(repr(v))
  6. # array([[0, 0, 0],
  7. # [0, 0, 0]], dtype=int16)

numpy.empty()

生成给定「尺寸」的数组,元素全未初始化,因为数值类型与C一致,所以未初始化的数据值是随机的,默认的类型是float

  1. import numpy as np
  2. v = np.empty((2, 2))
  3. print(repr(v))
  4. # array([[1.40735731e-311, 1.40736975e-311],
  5. # [8.61672470e-315, 8.61672486e-315]])
  6. v = np.array((2, 2), dtype=np.int16)
  7. print(repr(v))
  8. # array([[ 2678, 13056],
  9. # [ 54, 0]], dtype=int16)

numpy.ones()

生成给定「尺寸」的数组,元素全为 1 ,默认数值类型是numpy.float64

  1. import numpy as np
  2. v = np.ones(3)
  3. print(repr(v)) # array([1., 1., 1.])
  4. v = np.ones((2, 2), dtype=int)
  5. print(repr(v))
  6. # array([[1, 1],
  7. # [1, 1]])

numpy.full()

生成给定「尺寸」,给定「元素」的数组,数组的元素都相同,存储类型由给定元素决定。

  1. import numpy as np
  2. v = np.full(3, 666)
  3. print(repr(v)) # array([666, 666, 666])

numpy.arange()

numpy.arange([start,]stop, [step,]dtype=None)
生成给定范围和步长内的一维数组,步长可以是浮点数,数据类型根据范围和步长自动推断。

  1. import numpy as np
  2. v = np.arange(3)
  3. print(repr(v)) # array([0, 1, 2])
  4. v = np.arange(5, 2, -1)
  5. print(repr(v)) # array([5, 4, 3])
  6. v = np.arrange(1, 2, 0.3)
  7. print(repr(v)) # array([1. , 1.3, 1.6, 1.9])

numpy.linspace()

通过给定的范围元素个数来生成一维数组,与arange()相比,它生成的一维数组首位是可以确定的,步长通过计算来确定,而且这个函数默认是包括终止元素的。

  1. import numpy as np
  2. v = np.linspace(1, 2, 4)
  3. print(repr(v)) # array([1. , 1.33333333, 1.66666667, 2. ])
  4. v = np.linspace(1, 2, 4, endpoint=False) # 不包括终止位置 2
  5. print(repr(v)) # array([1. , 1.25, 1.5 , 1.75])