NumPy是Python的一种开源的数值计算扩展库,提供 数组支持以及相应的高效处理函数,它包含很多功能,如创建n维数组()矩阵,对数组进行函数运算,数值积分,线性代数计算,傅里叶变换和随机数产生等。
Why NumPy?
标准的Python用List(列表)保存值,可以当作数组使用,但因为列表中的元素可以是任何对象,所以浪费了CPU的运算时间和内存。NumPy的诞生弥补了这些缺陷,它提供了两种基本的对象:
参数名称 | 说明 |
---|---|
object | 接收array,表示想要创建的数组 |
dtype | 接收data-type,表示数组所需数据类型,未给定则选择保存数据对象所需的最小类型,默认为None。 |
ndmin | 接收int,指定生成数组应该具有的最小维数,默认为None。 |
#创建ndarray数组:
import numpy as np
data1 = [1,3,5,7] #列表
w1 = np.array(data1)
print('w1:',w1)
data2 = (1,2,3,4) #元组
w2 = np.array(data2)
print('w2:',w2)
data3 = [[1,2,3,6],[5,6,7,8]] #多维数组
w3 = np.array(data3)
print('w3:',w3)
#Output
#w1: [1 3 5 7]
#w2: [1 2 3 4]
#w3: [[1 2 3 6]
# [5 6 7 8]]
在创建数组时,NumPy会为新建的数组推断出一个合适的数据类型,并保存在dtype中,当序列中有整数和浮点数时,dtype会被定义为浮点数类型。
import numpy as np
data1 = [1,3,5,7.3] #列表
w1 = np.array(data1)
print(w1.dtype)
print('w1:',w1)
#Output
#float64
#w1: [1. 3. 5. 7.3]
#使用arrange创建数组
kk = np.arange(10)
print(kk)
#Output
#[0 1 2 3 4 5 6 7 8 9]
arrange函数可以通过指定初始值、终值和步长创建一维数组,创建的数组不包含终值。
kk = np.arange(0,15,1.5)
print(kk)
#Output
#[ 0. 1.5 3. 4.5 6. 7.5 9. 10.5 12. 13.5]
当arrange函数的参数是浮点型的时候,由于浮点的精度有限,通常不太可能预测或者数组元素的数量,由于这个原因,通常选用更好的函数linspace,它接收元素数量作为参数,通过指定初始值,终值和元素格式创建一维数组,默认包括终值。
#使用linspace函数创建数组
kk = np.linspace(1,10,4)
print(kk)
#Output
#[ 1. 4. 7. 10.]
#生成1~10的具有5个元素的等比数列数组
kk = np.logspace(0,1,5)
print(kk)
#Output
#[ 1. 1.77827941 3.16227766 5.62341325 10. ]
#使用zeros函数创建全零矩阵。
ll = np.zeros(4)
print(ll)
print("-----------------------")
kk = np.zeros(4,float)
print(kk)
print("-----------------------")
cc = np.zeros([3,3],int)
print(cc)
#Output
#[0. 0. 0. 0.]
#-----------------------
#[0. 0. 0. 0.]
#-----------------------
#[[0 0 0]
# [0 0 0]
# [0 0 0]]
可以看出,zeros函数默认类型为float64。
kk = np.diag([1,2,3,4])
print(kk)
#Output
# [[1 0 0 0]
# [0 2 0 0]
# [0 0 3 0]
# [0 0 0 4]]
kk = np.eye(4)
print(kk)
#Output
#[[1. 0. 0. 0.]
# [0. 1. 0. 0.]
# [0. 0. 1. 0.]
# [0. 0. 0. 1.]]
NumPy创建的ndarray对象属性,主要有shape、size等属性。具体如下表所示:
属性 | 说明 |
---|---|
ndim | 秩,即数据轴的个数 |
shape | 数组的维数 |
size | 数组元素个数 |
dtype | 数据类型 |
itemsize | 数组中每个元素的字节大小 |
序号 | 数据类型及描述 |
---|---|
1 | bool_ 存储为一个字节的布尔值(真或假) |
2 | int_ 默认整数,相当于 C 的long,通常为int32或int64 |
3 | intc 相当于 C 的int,通常为int32或int64 |
4 | intp 用于索引的整数,相当于 C 的size_t,通常为int32或int64 |
5 | int8 字节(-128 ~ 127) |
6 | int16 16 位整数(-32768 ~ 32767) |
7 | int32 32 位整数(-2147483648 ~ 2147483647) |
8 | int64 64 位整数(-9223372036854775808 ~ 9223372036854775807) |
9 | uint8 8 位无符号整数(0 ~ 255) |
10 | uint16 16 位无符号整数(0 ~ 65535) |
11 | uint32 32 位无符号整数(0 ~ 4294967295) |
12 | uint64 64 位无符号整数(0 ~ 18446744073709551615) |
13 | float_ float64的简写 |
14 | float16 半精度浮点:符号位,5 位指数,10 位尾数 |
15 | float32 单精度浮点:符号位,8 位指数,23 位尾数 |
16 | float64 双精度浮点:符号位,11 位指数,52 位尾数 |
17 | complex_ complex128的简写 |
18 | |
19 | complex128 复数,由两个 64 位浮点表示(实部和虚部) |
在NumPy.random模块中,提供了多种随机数的生成函数。如randint函数生成指定范围的随机整数来构成指定形状的数组。
用法:np.random.randint(low, high = None, size = None),表示生成随机的整数型矩阵,low 表示最小值, high表示最大值,size 是一个元组类型 size = shape。
#生成随机整数
kk = np.random.randint(100,200,size=(2,4)) #在100-200数据间生成一个2行4列的随机数数组
print(kk)
#Output
#[[167 189 168 135]
# [116 188 157 102]]
类似的,还有:
1). np.random.randn( ):生成标准的正太分布,没有固定的参数,每多加一个数字,代表多增加一个维度,高斯正太分布=高斯分布 ,分布:是统计学中的。标准的高斯分布 的中间值是0 ,最好的范围是1 -1,超出范围的都是异常值。
2). np.random.random(size):生成0-1之间的元素数组,size 表形状,random随即生产的范围是0-1之间,每个随机数都是一个维度。
3). np.random.rand( ):生成0-1之间的元素数组,和 np.random.random有一样的功能,random 需要 size来描述形状,而rand只需要我们直接给值,通过值的数量来确定形状。
4). np.random.normal(loc,scale,size):生成一个正太分布的数组,location 是定位的的值, scale 是波动值,size 是数据长度。
函数 | 说明 |
---|---|
seed | 确定随机数生成器的种子 |
permutation | 返回一个序列的随机排列或返回一个随机排列的范围 |
shuffle | 对一个序列进行随机排序 |
binomial | 产生二项分布的随机数 |
normal | 产生正态(高斯)分布的随机数 |
beta | 产生beta分布的函数 |
chisquare | 产生卡方分布的随机数 |
gamma | 产生gamma分布的随机数 |
uniform | 产生在[0,1]中均匀分布的随机数 |
对于已定义好的数组,可以通过reshape方法改变其数组维度,传入的参数为新维度的元组。reshape的参数中的其中一个可以设置为-1,表示数组的维度可以通过数据本身来推断。
kk0 = np.arange(8)
print("kk0: ",kk0)
kk1 = kk0.reshape(2,4)
print("kk1: ",kk1)
#Output
#kk0: [0 1 2 3 4 5 6 7]
#kk1: [[0 1 2 3]
# [4 5 6 7]]
kk0 = np.arange(15)
print("kk0: ",kk0)
kk1 = kk0.reshape(5,-1)
print("kk1: ",kk1)
#Output
#kk0: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
#kk1: [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]
# [12 13 14]]
kk0 = np.arange(15)
print("kk0: ",kk0)
kk1 = kk0.reshape(5,-1)
print("kk1: ",kk1)
kk2 = kk1.ravel()
print("kk2: ",kk2)
kk3 = kk1.flatten()
print("kk3: ",kk3)
#Output
#kk0: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
#kk1: [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]
# [12 13 14]]
#kk2: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
#kk3: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
数组合并用于多个数组间的操作,NumPy使用hstack函数、vstack函数、concatenate函数:完成数组的合并。
#横向合并:
kk1 = np.arange(6).reshape(3,2)
print(kk1)
print("----------")
kk2 = kk1 * 2
print(kk2)
print("----------")
kk3 = np.hstack((kk1,kk2))
print(kk3)
#Output
#[[0 1]
# [2 3]
# [4 5]]
#----------
#[[ 0 2]
# [ 4 6]
# [ 8 10]]
#----------
#[[ 0 1 0 2]
# [ 2 3 4 6]
# [ 4 5 8 10]]
与数组合并相反,NumPy提供了hsplit函数、vsplit函数和split函数分别实现数组的横向、纵向和指定方向的分割。
arr = np.arange(16).reshape(4,4)
print('横向分割为:\n',np.hsplit(arr,2))
print('纵向组合为:\n',np.vsplit(arr,2))
#Output
#横向分割为:
# [array([[ 0, 1],
# [ 4, 5],
# [ 8, 9],
# [12, 13]]), array([[ 2, 3],
# [ 6, 7],
# [10, 11],
# [14, 15]])]
#纵向组合为:
# [array([[0, 1, 2, 3],
# [4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
# [12, 13, 14, 15]])]
同样,split在参数axis = 1时实现数组的横向分割,axis = 0时则进行纵向分割。
数组转置是数组重塑的一种特殊形式,可以通过transpose方法进行转置。transpose 方法需要传入轴编号组成的元组。除了使用transpose外,也可以直接利用数组的T属性进行数组转置。
kk = np.arange(6).reshape(3,2)
print('矩阵:',kk)
print('-------------')
print('转置矩阵:',kk.transpose(1,0)) //# np.transpose(kk))
#Output
# 矩阵: [[0 1]
# [2 3]
# [4 5]]
# -------------
# 转置矩阵: [[0 2 4]
# [1 3 5]]
数组的T属性转置:
kk = np.arange(6).reshape(3,2)
print('矩阵:',kk)
print('-------------')
print('转置矩阵:',kk.T)
#Output
# 矩阵: [[0 1]
# [2 3]
# [4 5]]
# -------------
# 转置矩阵: [[0 2 4]
# [1 3 5]]
ndarray 的 swapaxes 方法实现轴对换:
kk = np.arange(6).reshape(3,2)
print('矩阵:',kk)
print('-------------')
print('轴对换:',kk.swapaxes(0,1))
#Output
# 矩阵: [[0 1]
# [2 3]
# [4 5]]
# -------------
# 轴对换: [[0 2 4]
# [1 3 5]]
一维数组的索引类似Python中的列表。
kk = np.arange(10)
print(kk)
print(kk[2])
print(kk[-1])
print(kk[2:5])
#Output
# [0 1 2 3 4 5 6 7 8 9]
# 2
# 9
# [2 3 4]
数组的切片返回的是原始数组的视图,不会产生新的数据,如果需要的并非视图而是要复制数据,则可以通过copy方法实现。
kk = np.arange(10)
print(kk)
kk1 = kk[1:3].copy()
print(kk1)
#Output
#[0 1 2 3 4 5 6 7 8 9]
#[1 2]
kk = np.arange(12).reshape(3,4)
print(kk)
print(kk[0,1:3]) #索引第0行中第1列到第2列的元素
print(kk[ :,2]) #索引第2列元素
print(kk[:1,:1]) #索引第0行第0列元素
#Output
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# [1 2]
# [ 2 6 10]
# [[0]]
kk = np.arange(12).reshape(3,4)
print(kk)
print('索引结果1: ',kk[(0,1),(1,3)]) #从两个序列的对应位置取出两个整数来组成下标:kk[0,1],kk[1,3]
print('索引结果2: ',kk[1:2,(0,2,3)]) #索引第一行中的0、2、3列元素
#Output
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 索引结果1: [1 7]
# 索引结果2: [[4 6 7]]