自学篇 python强大第三方库之numpy
一、numpy介绍
1.1 numpy基本语法
numpy最重要的一个特点就是其n维数组对象 ndarray ,它是一系列同类型数据的集合,以0为下标开始进行集合中元素索引(有点像行列式列表化)
numpy对象是用于存放同类型元素的多维数组。adarray中的每个元素在内存中都有相同存储大小的区域。
adarray内部由以下内容组成:
-
一个指向数据(内存或内存映射文件中的一块数据)的指针
-
数据类型或dtype,描述在数组中的固定大小值的格子
-
一个表示数组形状(shape)的元组,表示各维度大小的元组
-
一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要”跨过”的字节数
adarray的内部结构:
跨度可以是负数,这样会使数组在内存中向后移动,切片中obj[::-1]
或obj[:,::-1]
就是如此。
创建一个ndarray只需调用numpy下面的array
方法即可:
numpy.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)
array中各参数说明:
名称 | 描述 |
---|---|
object | 数组或嵌套的数列 |
dtype | 数组元素的数据类型,可选 |
copy | 对象是否需要复制,可选 |
order | 创建数组的样式,C为行方向,F为列方向,A为任意方向(默认) |
subok | 默认返回一个与基类类型一致的数组 |
ndmin | 指定生成数组的最小维度 |
# 例子
import numpy
# 一个维度
a=numpy.array([1,2,3])
print(a,type(a)) # --->[1 2 3] <class 'numpy.ndarray'>
# 多于一个维度
b=numpy.array([[1,2],[3,4]])
print(b,type(b))
# --->[[1 2]
# [3 4]] <class 'numpy.ndarray'>
# 最小维度
c_no_ndmin = numpy.array([1, 2, 3,4,5])
print (c_no_ndmin) # ---> [1 2 3 4 5]
c_admin=numpy.array([1,2,3,4,5],ndmin=2)
print(c_admin) # --->[[1 2 3 4 5]]
# dtype 参数
d=numpy.array([[1,2,3],[4,5,6],[7,8,9]],dtype=complex)
print(d)
# [[1.2+0.j 2. +0.j 3. +0.j]
# [4. +0.j 5. +0.j 6. +0.j]
# [7. +0.j 8. +0.j 9. +0.j]]
ndarray对象由计算机内存的连续一维部分组成,并结合索引模式,将每个元素映射到内存块中的一个位置。内存行以行顺序(C样式)或列顺序(FORTRAN或Matlab风格,即前述的F样式)来保存元素。
1.2 官方文档介绍
1.2.1 啥是numpy?
numpy是python中用于科学计算的模块。提供了多维数组的对象(multidimensional array object),各种派生对象(various derived objects),比如遮罩数组(masked array)、矩阵(matrix)等等以及对于数组快速操作的一系列步骤,包括数学的、逻辑的、形状拟合、排序、选择、IO、基础线代、基本数据操作、随机拟合等。
核心是n维的ndarray对象。这种封装好的多维数组内部数据具有统一的数据类型。
numpy的ndarray与python内置的list数据类型的区别:
-
arrays在创建时就固定了尺寸,python的list则可以在创建后增删改查数据(可变数据类型)。改变原ndarray的大小将创造一个新的array并且删除原来的array。
-
array中的数据必须是同一数据类型,就会在内存占据相同的大小。一个大array中可以包含多个array,其中每个小array可以实不同类型数据。
-
arrays在处理海量数据的高等数学操作以及其它类型操作时非常方便。比较python来说,使用array处理数据会比python内置的公式处理数据更加高效同时代码量更少。
-
越来越多用于科学和数学运算的python第三方库在使用numpy的arrays。虽然仍然支持python序列的input,但在处理数据前会先将数据转换成array类型。
由于在科学计算中序列占据空间的大小和处理速度是非常关键的。如果我们想将列表元素平方得到结果的话,在python中需要调用for循环,数据量较少时无明显区别,但在数据量较大时,python代码简洁的优点就被抵消了,且运行速度远远低于C,而numpy模块提供了一种简化代码量,同时实现接近C语言执行速度的数据类型,即array。
c = []
for i in range(len(a)):
c.append(a[i]*b[i])
for (i = 0; i < rows; i++): {
for (j = 0; j < columns; j++): {
c[i][j] = a[i][j]*b[i][j];
}
}
c = a * b
1.2.2 为啥numpy快?
上面的例子同样体现了numpy两外两大优势,向量化(Vectorization)和广播(broadcasting)。向量化表述了明显循环(looping)、索引(indexing)出现的情况。广播描述了潜在的元素之间的操作行为,不止可以进行算术操作,还可以进行逻辑、位、函数运算。在上面的例子中,a和b都可以是相同类型的多维数组或者一个标量(scalar)和一个数组或者不同类型两个数组。
1.2.3 谁还用numpy?
ndarray是一个类,拥有大量的方法和属性。其中的一些方法是模仿numpy名称空间中的函数而建立的。这就让编程者可以选择他们喜欢的范例(paradim)进行编程。
二、numpy基础
numpy对象主要是一个齐次多维数组(homogeneous multidimensional array)。是一个所有元素都是相同类型的,可以由非负数索引获得元素的表。在numpy中,我们把维度(dimensions)叫做轴(axes)。
举例来说,3D空间中一个点的坐标(coordinates of a point)[1, 2, 1]
有一轴。这个轴上面有三个元素,所以我们说这个轴长度为三。在下面的例子中,array有两个轴,第一个轴长度为2,第二个轴长度为3。
[[ 1., 0., 0.],
[ 0., 1., 2.]]
numpy的array类被叫做ndarray,也被叫做array。需要注意的是,python中的numpy.array和标准python库中的array.array不一样,前者只能操作一维数组并且提供很少的功能。
2.1 numpy属性
ndarray重要属性如下:
属性名 | 描述 |
---|---|
ndarray.ndim | array的维度的个数(二维,三维) |
ndarray.shape | array的维度。会返回一个元组显示每个方向的array大小。举例来说,一个矩阵n行m列,shape 就是(n,m) 。元组的元素个数就是上面的属性 |
ndarray.size | 数组中元素的总数 |
ndarray.dtype | array中元素的类型。numpy.int32, numpy.int16 , and numpy.float64 |
ndarray.itemsize | array中每个元素所占据的字节数。float64 has itemsize 8 (=64/8), while one of type complex32 has itemsize 4 (=32/8) |
ndarray.data | 包含数组实际元素的缓冲区。通常,我们不需要使用此属性,因为我们将使用索引工具访问数组中的元素。 |
>>>import numpy as np
>>>a = np.arange(15).reshape(3, 5)
>>>a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>>a.shape
(3, 5)
>>>a.ndim
2
>>>a.dtype.name
'int64'
>>>a.itemsize
8
>>>a.size
15
>>>type(a)
<class 'numpy.ndarray'>
>>>b = np.array([6, 7, 8])
>>>b
array([6, 7, 8])
>>>type(b)
<class 'numpy.ndarray'>
2.2 创建数组arrays
2.2.1 情况一:所有元素都知道
这里有好几种方法创建数组array。
你可以通过python内置的list
或者tuple
结合array
属性创建数组array。
>>> import numpy as np
>>> a = np.array([2,3,4])
>>> a
array([2, 3, 4])
>>> a.dtype
dtype('int64')
>>> b = np.array([1.2, 3.5, 5.1])
>>> b.dtype
dtype('float64')
一个经常会出现的错误是调用
array
创建数组array的时候只需要一个参数,如果传入多个参数会报错。
>>> a = np.array(1,2,3,4) # WRONG
Traceback (most recent call last):
...
TypeError: array() takes from 1 to 2 positional arguments but 4 were given
>>> a = np.array([1,2,3,4]) # RIGHT
array
将序列的序列转换成了二维数组,将序列的序列的序列转换成了三维数组。
>>> b = np.array([(1.5,2,3), (4,5,6)])
>>> b
array([[1.5, 2. , 3. ],
[4. , 5. , 6. ]])
在创建数组array的时候数据类型也可以被指定。
>>> c = np.array( [ [1,2], [3,4] ], dtype=complex )
>>> c
array([[1.+0.j, 2.+0.j],
[3.+0.j, 4.+0.j]])
2.2.2 情况二:知道元素个数不知道元素内容
通常来说,数组array的元素在一开始是不知道的,但是数组的大小是知道的。因此,numpy提供了一些函数来创造了一些有默认内容的方式来创建arrays。这能最小化扩展array可能产生的消耗。
zeros
函数创造了一个充满0的array,ones
可以创造一个充满1的array,以及empty
函数可以创建一个初始值是随机值以及取决于内存状态的array。默认情况下,array中元素的数据属性是float64
。
>>> np.zeros((3, 4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> np.ones( (2,3,4), dtype=np.int16 ) # dtype can also be specified
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=int16)
>>> np.empty( (2,3) ) # uninitialized
array([[ 3.73603959e-262, 6.02658058e-154, 6.55490914e-260], # may vary
[ 5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])
2.2.3 情况三:创建元素有序的array
如果想创建元素有序的array,numpy给我们提供了arange
函数,作用等同于python的内置函数range
,但是会返回一个array。
# arange一个参数默认从零开始
# arange两个参数指定起始位置,默认步长为一
# arange三个参数指定起始位置和步长
>>> np.arange( 10, 30, 5 )
array([10, 15, 20, 25])
>>> np.arange( 0, 2, 0.3 ) # it accepts float arguments
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
当使用arange
函数如果步长传入浮点数,因为浮点数准确性有限。由于这个原因,当我们想要数字分割间隔为浮点数的时候我们通常使用linspace
函数来接收我们想要元素的数量,让解释器帮我们划分间距。
a=numpy.arange(3)
print(a) # --->[0 1 2]
b=numpy.arange(0,4)
print(b) # --->[0 1 2 3]
c=numpy.arange(0,4,3)
print(c) # --->[0 3]
d=numpy.arange(0,2,0.3)
print(d) # --->[0. 0.3 0.6 0.9 1.2 1.5 1.8]
e=numpy.linspace(0,5,12)
print(e) # ---> [0. 0.45454545 0.90909091 1.36363636 1.81818182 2.27272727 2.72727273 3.18181818 3.63636364 4.09090909 4.54545455 5. ]
2.3 打印数组arrays
二、numpy的数据类型
2.1 数据类型
numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上,其中部分类型对应为 Python 内置的类型。下表列举了常用 NumPy 基本类型。
名称 | 描述 |
---|---|
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 numpy.bool_,numpy.int32,numpy.float32,等等。
2.2 数据类型对象dtype
数据类型对象(numpy.dtype 类的实例)用来描述与数组对应的内存区域是如何使用,它描述了数据的以下几个方面::
- 数据的类型(整数,浮点数或者 Python 对象)
- 数据的大小(例如, 整数使用多少个字节存储)
- 数据的字节顺序(小端法或大端法)
在结构化类型的情况下,字段的名称、每个字段的数据类型和每个字段所取的内存块的部分
如果数据类型是子数组,那么它的形状和数据类型是什么。
字节顺序是通过对数据类型预先设定 < 或 > 来决定的。 < 意味着小端法(最小值存储在最小的地址,即低位组放在最前面)。> 意味着大端法(最重要的字节存储在最小的地址,即高位组放在最前面)。