简介
numpy作为作为python中科学计算的核心库,包含了很多实用的数学函数,涵盖线性代数运算、傅里叶变换、随机数生成等功能。它提供了一个高性能多维数据对象,以及操作这个对象的工具。
1、多维数组创建(ndarray)
import numpy as np
# 数组的创建(ndarray)
print("####数组的创建####")
a1 = np.array([1, 2, 3])
a2 = np.array([[1, 2, 3], [4, 5, 6]])
a3 = np.array([range(5), range(5)])
a4 = np.array((1, 2, 3))
b1 = np.arange(10).reshape(2, 5)
b2 = np.arange(24).reshape(2, 3, 4)
b3 = np.arange(0, 10, 2) # 设置步长为2的数组
# 特殊数组的创建
print("####特殊数组的创建####")
c1 = np.zeros((3, 4)) # 零矩阵
c2 = np.zeros((3, 4), dtype="int32")
c3 = np.ones((3, 4)) # 元素全为1
c4 = np.ones((3, 4), dtype="int32")
c5 = np.eye(4, dtype="int32") # 对角线元素全为1
c6 = np.linspace(0, 10, 6) # 等差数组,总长度为6
c7 = np.repeat([1, 2, 3], 3) # 重复元素[1,2,3]三次
c8 = np.full((2, 3), 7) # 2行3列,元素全为7
c9 = np.random.random([3, 4]) # 随机数组3行4列
c10= np.tile(a1,(2,2)) # [[1,2,3,1,2,3] [1,2,3,1,2,3]]
numpy的主要对象是同种元素的多维数组,这是一个所有元素类型一样的元素表格,numpy的数组类型被称为ndarray.
2、多维数组的属性
# 数组的属性
d = np.arange(24).reshape(2, 3, 4)
array_rank = d.ndim # 数组的秩 3 (轴的个数,即d中元素需要几个下标表示)
array_shape = d.shape # 数组的维度 (2,3,4)
array_size = d.size # 数组中元素的总个数 24
array_dtype = d.dtype # 数组中元素的类型 int32
array_itemsize = d.itemsize # 每个元素的字节大小 4
array_flat = d.flat # 扁平迭代器(Iterable)
3、多维数组的方法
# 通用函数(axis=0:跨行计算,axis=1跨列计算)
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[6, 5, 4], [3, 2, 1]])
array1 = np.array([1,2,3,4,5])
np.sum(a, axis=0) # a.sum(axis=0)#求和
np.cumsum(a, axis=0) # 累计跨行求和
np.cumprob(a,axis=0) # 累计跨行求积
np.prod(array1) # 计算阶乘
np.cumprod(array1) # 计算累计阶乘
np.sin(a), np.sqrt(a), np.log(a), np.sum(a), np.min(a), np.max(a), np.mean(a), np.std(a)
4、多维数组索引和切片
a = np.array([[1, 2, 3], [4, 5, 6]])
# 扁平迭代器
a.flat[0][0]
# 索引
index_a1 = a[0][0]
index_a2 = a[0]
bool_a1 = a[a>1]
# 切片
slice_array1 = a[0:1, 0:1] # 获取第1行第1列元素
slice_array2 = a[0:, 0:1] # 获取第1行到最后一行,第1列的所有元素
slice_array3 = a[..., 0:1] # 获取所有行的第一列元素
slice_array4 = a[::-1] # 获取所有行所有列,行反转
5、多维数组的迭代
a = np.array([[1, 2, 3], [4, 5, 6]])
# 按行遍历数组
for row in a:
print(row) #[1,2,3] [4,5,6]
# 遍历数组中的每个元素
for ele in np.nditer(a):
print(ele) #1,2,3,4,5,6
# 遍历数组中的每个元素
for ele in a.flat:
print(ele) #1,2,3,4,5,6
6、更改数组的形状和类型
# 更改数组的形状
a = np.array([[1, 2, 3], [4, 5, 6]])
# 扁平迭代器
descent_a1 = a.flatten() # 将多维数组变成一维数组,修改一维数组不改变原始数组(拷贝)
descent_a2 = a.ravel() # 将多维数组变成一维数组,修改一维数组更改原始数组(视图)
a.shape = (3, 2) # 更改数组维数,原始数组发生改变
a.resize((3,2)) #更改数组维数,原始数组发生改变
a.transpose() # 数组转置
a.T # 数组转置
a.tolist() # 将ndarray转换成列表
a.astype(int) # 改变数组元素的数据类型
7、数组的组合和切割
# 数组的拼接和切割
array1 = np.arange(12).reshape(4, 3)
array2 = np.arange(12, 24, 1).reshape(4, 3)
print("####水平拼接####")
np.hstack((array1, array2))
np.column_stack((array1, array2))
np.concatenate((array1, array2), axis=1)
np.stack((array1, array2), axis=1) # 相同行元素组合在一起
print("####垂直拼接####")
np.vstack((array1, array2))
np.row_stack((array1, array2))
np.concatenate((array1, array2), axis=0)
np.stack((array1, array2), axis=0)
print("####深度拼接####")
np.dstack((array1, array2))
print("####水平切割####")
np.hsplit(array1, 3)
np.split(array1, 3, axis=1)
print("####垂直切割####")
np.vsplit(array1, 4)
np.split(array1, 4, axis=0)
print("####深度切割####")
np.dsplit(array1,4)
8、多维数组的视图(view)和拷贝(copy)
在执行函数时,其中一些返回数组的拷贝,而另一些返回数组的视图,python中关于对象复制有三种类型的使用方式:赋值、浅拷贝、深拷贝
赋值
赋值操作传递的是对象的引用,对象改变,复制的值也会发生改变
print("####赋值####")
a = [1, 2, 3, 4, 5, 6]
b = a
print(a is b) # True
print(id(a), id(b)) # 3401008 3401008
a[0]=100
print(b) # [100,2,3,4,5,6]
上面的代码,意味着两个对象指向了同一片内存空间,赋值操作只是复制了对象的引用,没有开辟新的内存空间,修改对象a的数值,对象b的数值也发生更改。
浅拷贝
浅拷贝(顶层复制)把对象每一个元素的id传递给另外一个变量,浅拷贝有三种形式:切片操作、工厂函数、copy函数
切片操作
numpy中切片出来的数组都是原始数据的一个视图,并不是原数据的拷贝。python中切片出来的是原数据的一个拷贝。
print("####浅拷贝####")
print("----切片操作----")
a = [1, 2, 3]
a[1] = a[:]
print(a) # a=[1,[1,2,3],3]
print(id(a) is id(a[1])) # False
上述代码先解引用得到a所指向的对象[1,2,3],然后执行[1,2,3][:]复制操作得到新的对象,内容也是[1,2,3],然后a[1]指向了这个新的对象,最后a的值为[1,[1,2,3],3]
工厂函数
print("####浅拷贝####")
print("----工厂函数----")
a = [1, 2, 3]
a[1] = list(a)
print(a) # a=[1,[1,2,3],3]
print(id(a) is id(a[1])) # False
copy函数
print("####浅拷贝####")
print("----copy函数----")
import copy
a = [1, 2, 3]
a[1] = copy.copy(a)
print(a) # a=[1,[1,2,3],3]
print(id(a) is id(a[1])) # False
深拷贝
深拷贝复制的是对象的所有元素,包括多层嵌套的元素,deepcopy本质上是递归copy。
print("----深拷贝----")
import copy
a = [1, [1, 2, 3], 3]
b = copy.deepcopy(a)
print(id(a), id(b)) # False
b[1] = 10
print(a) # [1,[1,2,3],3]
numpy中的视图(view)和拷贝(copy)
视图(修改对象元素,新对象元素也会发生改变)
print("####视图####")
a = np.array([1, 2, 3])
b = a[0:2] # 切片视图对象
c = a.view() # 视图对象
d = a.ravel() # 降维视图对象
a[0] = 100
print(b) # [100,2]
print(c) # [1,2,3]
print(d) # [1,2,3]
拷贝(原始数组改变,拷贝对象不改变)
import numpy as np
a = np.array([1, 2, 3])
e = np.copy(a)
a[0] = 10
print(e) # [1,2,3]
9、numpy广播机制
广播机制:如果两个ndarray数组的后缘维度(即从末尾开始算起的维度)的轴长度相等或者一方为1,则他们之间可以进行广播,广播会在缺失或长度为1的维度上进行。
a = np.arange(12).reshape(3, 4)
b = np.arange(4).reshape(4, )
print(a + b)
10、花式索引
花式索引用来获取(take)和设置(put)数组子集
array1 = np.array([1, 2, 3, 4, 5, 6])
index = [0, 2, 3]
# 取出指定索引的数组子集
print(array1.take(index)) # [1,3,4]
# 设置指定索引的数值
array1.put(index, 5) # 全部设置为5
array1.put(index, [1, 2, 3])
array1.clip(1,2) # clip函数表示把数组中小于1的数设置为1,大于2的数设置为2
np.where(array1 > 3) # 筛选出数组中大于3的元素,返回元素下标
np.compress(array1 > 3, array1) # 筛选出数组中大于3的元素,并返回元素值