numpy数组初探

NumPy数组

Numpy 数组是一个多维数组对象,称为 ndarray,由实际的数据和描述这些数据的元数据组成。大部分操作仅针对元数据,而不改变底层实际的数据。

关于 NumPy 数组需要知道:NumPy 数组的下标从 0 开始;同一个 NumPy 数组中的所有元素的类型必须是相同的。

NumPy 数组属性

NumPy 数组的维数称为秩(rank),每一个线性的数组称为一个轴(axes),秩其实是描述轴的数量。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中的每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴,第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。

NumPy 的数组中比较重要的 ndarray 对象属性有:

  • ndarray.ndim - 数组的维数/秩。最常见为二维数组。
  • ndarray.shape - 数组的维度。为一个表示数组在每个维度上大小的整数元组。例如二维数组中,表示数组的“行数”和“列数”。ndarray.shape 返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性。
  • ndarray.size - 数组元素的总个数,等于 shape 属性中元组元素的乘积。
  • ndarray.dtype - 表示数组中元素类型的对象,可使用标准的 Python 类型创建或指定 dtype
  • ndarray.itemsize - 数组中每个元素的字节大小。例如一个元素类型为 float64 的数组 itemsize 属性值为 8,一个元素类型为 complex32 的数组 itemsize 属性为 4。
  • ndarray.data - 包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。

创建数组

numpy.array()

1
2
3
4
5
6
7
8
9
>>> import numpy
>>> a = numpy.array([2,3,4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int64')
>>> b = numpy.array([1.2, 3.5, 5.1])
>>> b.dtype
dtype('float64')

使用 numpy.array() 函数创建时,参数必须是由方括号括起的列表,而不能使用多个数值作为参数调用。

1
2
3
4
>>> a = numpy.array(1,2,3,4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: only 2 non-keyword arguments accepted

可使用双重序列表示二维的数组,三重序列表示三维数组,以此类推:

1
2
3
4
>>> b = numpy.array([(1.5,2,3),(4,5,6)])
>>> b
array([[ 1.5, 2. , 3. ],
[ 4. , 5. , 6. ]])

可以在创建时显式指定数组中元素的类型:

1
2
3
4
>>> c = numpy.array([[1,2],[3,4]], dtype=complex)
>>> c
array([[ 1.+0.j, 2.+0.j],
[ 3.+0.j, 4.+0.j]])

numpy.zeros()、numpy.ones()、numpy.empty()

通常刚开始时数组的元素未知,而数组的大小已知。因此 NumPy 提供了一些使用占位符创建数组的函数。这些函数有助于满足除了数组扩展的需要,同时降低了高昂的运算开销。

用函数 numpy.zeros() 可创建一个全是 0 的数组,用函数 numpy.ones() 可创建一个全为 1 的数组,函数 numpy.empty() 创建一个内容随机并且依赖于内存状态的数组。默认创建的数组类型(dtype)都是 float64。

可以用 d.dtype.itemsize 来查看数组中元素占用的字节数目:

1
2
3
4
5
6
7
8
9
>>> d = numpy.zeros((3,4))
>>> d.dtype
dtype('float64')
>>> d
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
>>> d.dtype.itemsize
8

也可以自己制定数组中元素的类型:

1
2
3
4
5
6
7
8
9
10
11
>>> numpy.ones((2,3,4), dtype=numpy.int8)
array([[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]],
[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]], dtype=int8)
>>> numpy.empty((2,3))
array([[ 0., 0., 0.],
[ 0., 0., 0.]])

numpy.arange()

NumPy 提供一个类似 arange() 的函数返回一个数列形式的数组:

1
2
3
4
>>> numpy.arange(10,30,5)
array([10, 15, 20, 25])
>>> numpy.arange(0,2,0.5)
array([ 0. , 0.5, 1. , 1.5])

numpy.linspace()

numpy.arange() 使用浮点数参数时,由于浮点数精度有限,通常无法预测获得的元素个数。因此,最好使用函数 numpy.linspace() 去接收我们想要的元素个数来代替用 range 来指定步长:

1
2
>>> numpy.linspace(-1, 0, 5)
array([-1. , -0.75, -0.5 , -0.25, 0. ])

数组中的元素是通过下标来访问的,可以以切片的形式访问数组中多个元素。

NumPy基本数据类型

名称 类型 取值范围
bool 用一个字节存储的布尔类型 True / False
int8 整数 -128 ~ 127
int16 整数 -32768 ~ 32767
int32 整数 -2^31 ~ 2^31-1
int64 整数 -2^63 ~ 2^63-1
uint8 无符号整数 0 ~ 255
uint16 无符号整数 0 ~ 65535
uint32 无符号整数 0 ~ 2^32-1
uint64 无符号整数 0 ~ 2^64-1
float16 半精度浮点数16位 正负号1位,指数5位,精度10位
float32 单精度浮点数32位 正负号1位,指数8位,精度23位
float64 双精度浮点数64位 正负号1位,指数11位,精度52位
float 双精度浮点数64位 正负号1位,指数11位,精度52位
complex64 复数 分别用两个32位浮点数表示实部和虚部
complex128 复数 分别用两个64位浮点数表示实部和虚部
complex 复数 分别用两个64位浮点数表示实部和虚部

NumPy类型转换

1
2
3
4
5
6
7
8
9
10
>>> numpy.float64(42)
42.0
>>> numpy.int8(42.0)
42
>>> numpy.bool(42)
True
>>> numpy.bool(42.0)
True
>>> numpy.float(True)
1.0

许多函数的参数中可以指定参数的类型,这个类型参数是可选的,如下:

1
2
>>> numpy.arange(7, dtype=numpy.uint16)
array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)

输出数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> a = numpy.arange(6)
>>> print a
[0 1 2 3 4 5]
>>> b = numpy.arange(12).reshape(4,3)
>>> print b
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
>>> c = numpy.arange(24).reshape(2,3,4)
>>> print c
[[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]]

如果一个数组太长,则 NumPy 自动省略中间部分而只打印两端的数据:

1
2
3
4
5
6
7
8
9
10
11
>>> print numpy.arange(10000)
[ 0 1 2 ..., 9997 9998 9999]
>>> print numpy.arange(10000).reshape(100,100)
[[ 0 1 2 ..., 97 98 99]
[ 100 101 102 ..., 197 198 199]
[ 200 201 202 ..., 297 298 299]
...,
[9700 9701 9702 ..., 9797 9798 9799]
[9800 9801 9802 ..., 9897 9898 9899]
[9900 9901 9902 ..., 9997 9998 9999]]

可以通过设置 set_printoptions() 函数来禁用 NumPy 的这种行为并强制打印整个数组:

1
2
>>> numpy.set_printoptions(threshold='nan')
>>> print numpy.arange(10000).reshape(100,100)

此后输出时数组的所有元素都会显示出来。