Python数据处理:IPython使用学习笔记
Python数据处理:Numpy 学习笔记
Python数据处理:Pandas 学习笔记
《NumPy快速入门手册》写得很好,也推荐阅读
一. numpy
1. 介绍
2. numpy引用
"""numpy的主要对象是一个规范格式的多维数组"""
import numpy as np
二. 创建numpy数组
1. 通过list、tuple或其他序列,创建数组
### 通过list、tuple或其他序列,创建数组
data = np.array([[1, 2, 3], [4, 5, 6]]) # 生成np的数组,注意入参不能是多个元素:如np.array(1,2,3,4),否则会报错
data2 = np.array([[1, 3], [5, 7], [9, 11]], dtype=complex) # 可以直接指定数据类型dtype
print(data2)
''' 可以看到数据格式转成了复数
[[ 1.+0.j 3.+0.j]
[ 5.+0.j 7.+0.j]
[ 9.+0.j 11.+0.j]]
'''
2. 创建特定格式和内容的数组
a. 全一数组
# 全一数组
one_np = np.ones([3,2], dtype=int) # 创建全为1的二维数组,第一个参数shape决定了数组的格式
print(one_np)
'''
[[1 1]
[1 1]
[1 1]]
'''
b. 全零数组
# 全零数组
zero_np = np.zeros([2, 3, 2], dtype=float) # 创建了一个三维数组,每个数组元素都是0
print(zero_np)
'''
[[[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]
[[ 0. 0.]
[ 0. 0.]
[ 0. 0.]]]
'''
c. 空随机数组
# 空随机数组
random_np = np.empty([2, 2]) # 根据系统的状态随机生成一些占位元素,数组完全是随机的
print(random_np)
'''
[[ 1.33511562e-306 6.23040373e-307]
[ 1.20161730e-306 1.02360527e-306]]
'''
3. 数字序列数组
### 数字序列数组
# arange() 起点start + 终点stop(不包含) + 总共节点数step
data3 = np.arange(1, 9, 2) # 类似于range()函数, 一维数组
print(data3) # [1 3 5 7]
# linspace() 起点start + 终点stop(包含) + 总共节点数num
data4 = np.linspace(0, 5) # linspace(start, stop, num=50)生成从起点到终点(包括),均匀间隔的一维数组。
# 其中num默认为50,表示数组长度(因此元素间隔宽度为(stop - start)/num )
print(data4)
'''
array([ 0. , 0.10204082, 0.20408163, 0.30612245, 0.40816327,
0.51020408, 0.6122449 , 0.71428571, 0.81632653, 0.91836735,
1.02040816, 1.12244898, 1.2244898 , 1.32653061, 1.42857143,
1.53061224, 1.63265306, 1.73469388, 1.83673469, 1.93877551,
2.04081633, 2.14285714, 2.24489796, 2.34693878, 2.44897959,
2.55102041, 2.65306122, 2.75510204, 2.85714286, 2.95918367,
3.06122449, 3.16326531, 3.26530612, 3.36734694, 3.46938776,
3.57142857, 3.67346939, 3.7755102 , 3.87755102, 3.97959184,
4.08163265, 4.18367347, 4.28571429, 4.3877551 , 4.48979592,
4.59183673, 4.69387755, 4.79591837, 4.89795918, 5. ])
'''
4. 随机数
a. np.random.rand 生成[0,1)区间内平均分布的数组,参数为维度
### 随机数
# 生成[0,1)区间内平均分布的数组,参数为维度
data5 = np.random.rand(2, 3, 5)
print(data5)
'''
[[[ 0.11460522 0.78475528 0.41318688 0.9830661 0.23276821]
[ 0.31333353 0.99497377 0.31270973 0.55575352 0.30095844]
[ 0.83803498 0.07725709 0.60617707 0.17494517 0.7324532 ]]
[[ 0.03576562 0.84033749 0.81820702 0.46633063 0.06972207]
[ 0.00538072 0.44754953 0.23233634 0.78536293 0.43381988]
[ 0.85224057 0.40323818 0.07592376 0.23596046 0.49922436]]]
'''
b. np.random.randn 生成标准正态分布规律的数组(数出现的概率满足标准正太分布),参数为维度
# 生成标准正态分布规律的数组(数出现的概率满足标准正太分布),参数为维度
data6 = np.random.randn(2, 3, 5)
print(data6)
'''
[[[-0.51493028 1.78516665 -0.38657793 0.70038985 -1.24254944]
[-0.80613041 0.63745159 0.74201648 0.39451194 -0.94476024]
[-0.47833675 -0.92092758 1.01658297 0.85712149 -0.21944187]]
[[ 1.3295873 -0.10871527 0.31088519 -0.60094403 1.80437504]
[-0.3851662 -0.26422884 1.03784294 -0.44199909 0.83116801]
[-0.03563173 -0.66946972 0.45256832 0.17121998 0.2120946 ]]]
'''
c. 生成指定范围的随机数
# 生成指定范围的随机整数
np.random.randint(1, 7, 10) # 开区间,不可能取7 ,array([5, 3, 6, 1, 6, 1, 6, 5, 4, 3])
np.random.random_integers(1,7,10) # 闭区间,可以取到7 array([5, 1, 1, 7, 7, 2, 6, 5, 1, 2])
np.random.random() # [0,1)内随机数 本例:0.3825271804785396
d. np.random.choice 随机选择
# 随机选择
np.random.choice(10,size=2) # array([7, 4])
np.random.choice(10,size=(3,4)) # 设置shape
'''
array([[4, 9, 5, 7],
[6, 6, 5, 1],
[6, 5, 5, 0]])
'''
np.random.choice(['a','b','c'],size=[2,2]) # 从给出的list中随机选择生成数组
'''
array([['c', 'b'],
['c', 'b']],
dtype='<U1')
'''
二. 数组的属性
"""数组的属性"""
data = np.array([[1, 2, 3], [4, 5, 6]])
data.ndim # 数组的维度 本例:2
data.shape # 数组的形状,返回一个元组,表示各个方向的长度,元组本身的长度等于数组的维度. 本例:(2, 3)
data.size # 数组的大小,等于shape元组内各个元素的乘积, 本例:6
data.dtype # 数组内部元素的数据类型, 本例:dtype('int32')
data.itemsize # 数组内元素占计算机内存的大小(多少个Byte), 本例:4
data.data # 数组在内存中的地址,一般很少用,本例:<memory at 0x00000000070AC1F8>
三. 数组维度及元素类型转换
1. 重新修改维度(常用)
### 重新修改维度(常用)
data_shaped1 = data.reshape(3,2)
print(data_shaped1)
'''
[[1 2]
[3 4]
[5 6]]
'''
# 利用arrange() 和 reshape() 生成多维数组
data_shaped3 = np.arange(24).reshape(3, -1, 4) #如果某一个方向设为-1,则会自动计算
print(data_shaped3)
''' 可以看到,第二维度被自动计算为2
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]
[[16 17 18 19]
[20 21 22 23]]]
'''
### resize()
# 与 reshape()相似,不过resize()会修改原数组
2. np数组转换为list
### 转换为list
list_np = one_np.tolist() # [[1, 1], [1, 1], [1, 1]]
3. np.astype() 转换元素类型
### 转换类型 astype() 在转换中,可能会损失精度
data2_int = data2.astype(int) # 元素数据类型,从原先的复数complex转换为int
print(data2_int)
'''
[[ 1 3]
[ 5 7]
[ 9 11]]
'''
4. 数组转置
### 数组转置
np.transpose(data_shaped1)
'''
array([[1, 3, 5],
[2, 4, 6]])
'''
# 多维数组转置
np.transpose(data_shaped3) # 多维数组转置,就是坐标的reverse,然后组成新数组,注意数据交换
'''
array([[[ 0, 8, 16], d[0,0,0], d[1,0,0], d[2,0,0]
[ 4, 12, 20]], d[0,1,0], d[1,1,0], d[2,1,0]
[[ 1, 9, 17], d[0,0,1], d[1,0,1], d[2,0,1]
[ 5, 13, 21]], d[0,1,1], d[1,1,1], d[2,1,1]
[[ 2, 10, 18], d[0,0,2], d[1,0,2], d[2,0,2]
[ 6, 14, 22]], d[0,1,2], d[1,1,2], d[2,1,2]
[[ 3, 11, 19], d[0,0,3], d[1,0,3], d[2,0,3]
[ 7, 15, 23]]]) d[0,1,3], d[1,1,3], d[2,1,3]
'''
5. 转换一维数组
### ravel() 逐行取元素并返回一个一维数组
print(np.ravel(data_shaped3)) # [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
四. 数组的完全不复制(全部引用)、指代(局部引用)、深度复制
1. 完全不复制
### 1. 完全不复制
a = np.arange(4)
b = np.arange(4)
b is a # b和a现在还不是同一引用,为False
b = a
b is a # b和a是同一引用,为True
a.shape # 此时是(4,)
b.shape = (2,2) # 因为是同一引用,所以也会修改a的形状
a.shape # 变为(2, 2)
2. 指代 (切片也是如此)
### 2. 指代 (切片也是如此)
a = np.arange(12,24).reshape(3,4)
b = a.view() # 返回一个指代,但还是引用了同一数组
b is a # False
b[1,2] = 678
print(a)
''' 可以看到a[1,2]也变成了678
[[ 12 13 14 15]
[ 16 17 678 19]
[ 20 21 22 23]]
'''
3. 深度复制
### 3. 深度复制
a = np.arange(12,24).reshape(3,4)
b = a.copy()
b is a # False
b[1,1] = 111
print(b)
'''
[[ 12 13 14 15]
[ 16 111 18 19]
[ 20 21 22 23]]
'''
print(a)
''' a 没变
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
'''
五. 数组取值及分片
1. 多维数组通过索引取某一元素
### 多维数组通过索引取某一元素
c = np.arange(12).reshape(3, 4) # 创建一个3*4的二维数组
print(c)
'''
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
'''
c[1,3] # 取第二行第四列的元素,本例:7
c[1][3] # 取第二行第四列的元素,本例:7
2. 一维数组分片 arr[i:j:k]
i决定起始,j决定结束,k决定步进,都可以为负数,其中k为负则倒序取值
### 一维数组分片 arr[i:j:k] i决定起始,j决定结束,k决定步进,都可以为负数,其中k为负则倒序取值
b = np.arange(1,20,2)
b # array([ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19])
b[2] # 取第三项的元素, 本例:5
b[2:4] # 取第三、四项的子分片,本例:array([5, 7])
b[:5:2] # 在原数组前五项中,步进为2的取数组成新数组,本例:array([1, 5, 9])
b[-3:1:-2] # 从倒数第三项('15')开始,从后向前步进2格取值,直到第二项('3',不包含此项) 本例:array([15, 11, 7])
## 注意:虽然语法相似,但不同于list的分片(创建副本),np的分片是不创建副本的,修改分片中的元素,会影响到原数组的元素
sub_b = b[2:7:3] # sub_b = array([ 5, 11])
sub_b[1] = 1 # 此时sub_b变为了array([5, 1])
b # 同时原数组也发生了变化:array([ 1, 3, 5, 7, 9, 1, 13, 15, 17, 19])
### 如果想创建绝对的副本,则要用copy()
b = np.arange(1,20,2)
duplicate_b = b[2:7:3].copy() # duplicate_b = array([ 5, 11]), 使用copy创建副本
duplicate_b[1] = 1 # 此时duplicate_b变为了array([5, 1])
b # 原数组没有变:array([ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19])
4. 多维数组分片
### 多维数组分片
c = np.arange(12).reshape(3, 4) # 创建一个3*4的二维数组
print(c)
'''
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
'''
sub_c = c[1:3,1:3] # 取2、3行和2、3列的子数组
print(sub_c)
'''
[[ 5 6]
[ 9 10]]
'''
## 多维数组倒序分片
sub_c = c[::-2,1:3] # 取所有行步进为-2(从后向前)和2、3列组成的子数组
print(sub_c)
'''
[[ 9 10] # 先取的第三行的9,10
[ 1 2]] # 再取的第一行的1,2
'''
使用分片,批量修改元素及顺序
### 使用分片,批量修改元素(因为只是引用)
b = np.arange(1,20,2) # array([ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19])
b[1:9:2] += 1 # 从第2项到第9项,步进为2的数都自增1
b # array([ 1, 4, 5, 8, 9, 12, 13, 16, 17, 19])
### 拓展:重新排序
c = b[[0,2,1]]
print(c)
'''
[[10 11 12 13]
[18 19 20 21] 第二行和第三行交换了顺序
[14 15 16 17]]
'''
d = b[:,[3,0,-2,1]]
print(d)
''' 列上交换了顺序
[[13 10 12 11]
[17 14 16 15]
[21 18 20 19]]
'''
六. 高级索引
1. 整数索引
a. 数组arr_index为索引,从一维数组array中筛选出新的数组
## 数组arr_index为索引,从一维数组array中筛选出新的数组
a = np.arange(10,20) # a: array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
arr_index = np.array(([3,4,5],[1,2,3]))
a_new = a[arr_index]
print(a_new)
''' 可以看到取的数组的格式跟arr_index一致,每个元素为原数组在索引arr_index[i]处的值
[[13 14 15] a[3]=13, a[4]=14, a[5]=15
[11 12 13]] a[1]=11, a[2]=12, a[3]=13
'''
b. 数组arr_index为索引,从多维数组array中筛选出新的数组
## 数组arr_index为索引,从多维数组array中筛选出新的数组
b = np.arange(10,22).reshape(3,4)
print(b)
"""
[[10 11 12 13]
[14 15 16 17]
[18 19 20 21]]
"""
arr_index = np.array([[0,2,1],[1,2,0]])
e = b[arr_index]
print(e)
''' 本质上与一维数组和多维索引的结果类似,整体数组的形状还是按照索引arr_index的形状,
只是这里的索引搜出来的元素不是简单数据,而是一维数组,所以整个结果数组扩充为了三维数组
[[[10 11 12 13] b[0]=[10 11 12 13]
[18 19 20 21] b[2]=[18 19 20 21]
[14 15 16 17]] b[1]
[[14 15 16 17] b[1]
[18 19 20 21] b[2]
[10 11 12 13]]] b[0]
'''
c. 列表、元组list_index为索引,从多维数组array中筛选出新的数组
## 列表、元组list_index为索引,从多维数组array中筛选出新的数组
b = np.arange(10,22).reshape(3,4)
print(b)
'''
[[10 11 12 13]
[14 15 16 17]
[18 19 20 21]]
'''
list_index = ([0,2,1],[1,2,0]) # 注意这里是list、tuple或者其他简单序列,不是np.array
b_new = b[list_index]
print(b_new)
''' 通过索引来取元素组成新的结果
[11 20 14] a[0,1]=11, a[2,2]=20, a[1,0]=14
2. 布尔索引
a. 布尔索引的意义
### 布尔索引 通过True/False的数组,来索引数组
m = np.random.rand(30).reshape(10, 3) # 创建一个10 * 3 的二维数组
print(m)
'''
[[ 0.64877021 0.72179137 0.56534942]
[ 0.66861906 0.99436 0.09971997]
[ 0.71550022 0.39179217 0.69544798]
[ 0.76190541 0.71990526 0.5056289 ]
[ 0.09218896 0.20907768 0.53118 ]
[ 0.04977315 0.79410303 0.86770033]
[ 0.39507158 0.42490585 0.48495278]
[ 0.18026899 0.47850156 0.13560222]
[ 0.11837795 0.67394728 0.7619298 ]
[ 0.23708205 0.93920253 0.79138269]]
'''
m_select = m[[True,False,False,False,True,True,False,False,False,False]] # 总共10个Boolean值,对应m的10行
print(m_select)
''' 通过True值,筛选出第一行、第五、六行的数据组成子数组
[[ 0.64877021 0.72179137 0.56534942]
[ 0.09218896 0.20907768 0.53118 ]
[ 0.04977315 0.79410303 0.86770033]]
'''
# 这样乍一看觉得用布尔值多此一举,用数筛选更方便,但如果有两个数组,之间存在对应关系,布尔值搜索就十分方便
n = np.array(['小明','小红','李白','小明','小明','李白','小红','张伟','李白','张伟']) # n中有10个人,对应m的十行数据
# 现在我们要筛选出属于'小红'的数据
m_select2 = m[n=='小红']
print(m_select2)
''' 筛选出属于小红的第二行、第七行数据
[[ 0.66861906 0.99436 0.09971997]
[ 0.39507158 0.42490585 0.48495278]]
'''
b. 布尔索引判断的拓展
## 还可以再用切片或者筛选
m_select3 = m[n=='小红',1] # 筛选出第二列的数据
print(m_select3) # [ 0.99436 0.42490585]
## 与或非运算
m_select4 = m[n!='小红',:2] # 筛选出不是小红的前两列数据
print(m_select4)
'''
[[ 0.64877021 0.72179137]
[ 0.71550022 0.39179217]
[ 0.76190541 0.71990526]
[ 0.09218896 0.20907768]
[ 0.04977315 0.79410303]
[ 0.18026899 0.47850156]
[ 0.11837795 0.67394728]
[ 0.23708205 0.93920253]]
'''
m_select5 = m[(n=='小红')|(n=='李白')] # 筛选出小红或者李白的数据
print(m_select5)
'''
[[ 0.66861906 0.99436 0.09971997]
[ 0.71550022 0.39179217 0.69544798]
[ 0.04977315 0.79410303 0.86770033]
[ 0.39507158 0.42490585 0.48495278]
[ 0.11837795 0.67394728 0.7619298 ]]
'''
七. 数组元素替换和填充
1. 布尔索引
"""数组元素替换和填充 布尔索引 + np.where() """
### 通过布尔索引,实现元素替换与填充
x = np.array([[1,2],[np.nan, 3],[np.nan, np.nan]])
print(x)
'''
[[ 1. 2.]
[ nan 3.]
[ nan nan]]
'''
np.isnan(x)
'''
array([[False, False],
[ True, False],
[ True, True]], dtype=bool)
'''
x[np.isnan(x)] # 筛选出是nan元素组成新一维数组, array([ nan, nan, nan])
x[np.isnan(x)] = 0 # 将x中是nan的元素,都替换为0,通过布尔索引实现替换元素的功能
print(x)
'''
[[ 1. 2.]
[ 0. 3.]
[ 0. 0.]]
'''
x[~np.isnan(x)] # 筛选出是nan元素组成新一维数组, array([ 1., 2., 3.])
2. 筛选函数where(condition, a, b)
condition元素为布尔值,能起到和布尔索引同样的功能
### 筛选函数where(condition, a, b) condition元素为布尔值,能起到和布尔索引同样的功能
a = np.arange(1,10,2) # array([1, 3, 5, 7, 9])
b = np.arange(2,11,2) # array([ 2, 4, 6, 8, 10])
f = np.array([True,True,False,True,False])
r = np.where(f, a, b) # 如果f某位置的值为True则取对应位置的a的值,否则取b的值
'''
array([ 1, 3, 6, 7, 10])
'''
# a/b可以不为数组,用法如下
a = np.random.rand(12).reshape(3,4)
'''
array([[ 0.21251241, 0.28023144, 0.01282137, 0.24889945],
[ 0.55515714, 0.95901587, 0.34933226, 0.80928682],
[ 0.69281057, 0.63581292, 0.960359 , 0.7399842 ]])
'''
r = np.where(a>0.5, 1, 0)
'''
array([[0, 0, 0, 0],
[1, 1, 0, 1],
[1, 1, 1, 1]])
'''
r2 = np.where(a>0.5, a, 0)
'''
array([[ 0. , 0. , 0. , 0. ],
[ 0.55515714, 0.95901587, 0. , 0.80928682],
[ 0.69281057, 0.63581292, 0.960359 , 0.7399842 ]])
'''
## 与r2相同结果的方法实现
a[a<=0.5] = 0 # 将a中所有小于等于0.5的都设为0
print(a)
'''
[[ 0. 0. 0. 0. ]
[ 0.55515714 0.95901587 0. 0.80928682]
[ 0.69281057 0.63581292 0.960359 0.7399842 ]]
'''
八. 数组的组装拼接和分割
1. 拼接数组
a = np.array([[1,2],[3,4]])
b = np.array([['A','B'],['C','D']])
### 竖直拼接
v = np.vstack((a,b))
print(v)
''' 有意思的是,数字也被转换string格式了
[['1' '2']
['3' '4']
['A' 'B']
['C' 'D']]
'''
### 水平拼接
h = np.hstack((a,b))
print(h)
'''
[['1' '2' 'A' 'B']
['3' '4' 'C' 'D']]
'''
2. 分割数组
### 分割数组
d = np.arange(32).reshape(4,8)
print(d)
'''
[[ 0 1 2 3 4 5 6 7]
[ 8 9 10 11 12 13 14 15]
[16 17 18 19 20 21 22 23]
[24 25 26 27 28 29 30 31]]
'''
# 水平分割
d_split = np.hsplit(d, (3,5)) # 分割节点在第4、6两列
for item in d_split:
print(item)
print("********")
''' 分割结果
[[ 0 1 2]
[ 8 9 10]
[16 17 18]
[24 25 26]]
********
[[ 3 4]
[11 12]
[19 20]
[27 28]]
********
[[ 5 6 7]
[13 14 15]
[21 22 23]
[29 30 31]]
********
'''
# 水平分割
d_split = np.vsplit(d, 2) # 分割节点在第3列
'''
[array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15]]),
array([[16, 17, 18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29, 30, 31]])]
'''
3. 查找特殊坐标
### 查找特殊坐标
x.nonzero() # 获取x中不为0的元素的坐标,每个维度为一行 本例:(array([0, 0, 1], dtype=int64), array([0, 1, 1], dtype=int64))
np.transpose(x.nonzero()) # 转换为横纵坐标对为元素的数组,更直观
''' 正好与x中三个不为0的元素的横纵坐标对应
array([[0, 0], x[0,0] = 1
[0, 1], x[0,1] = 2
[1, 1]], dtype=int64) x[1,1] = 3
'''
九. 数组操作符运算
1. 数组与数的计算
是将数组中的每个单元,都与此数进行运算后的结果再组成数组返回
### 数组与数的计算,是将数组中的每个单元,都与此数进行运算后的结果再组成数组返回
plus_np = one_np + 3 # 数组内,每个元素都 + 3
print(plus_np)
'''
[[4 4]
[4 4]
[4 4]]
'''
mul_np = data * 2 # 数组内,每个元素都乘以2
print(mul_np)
'''
[[ 2 4 6]
[ 8 10 12]]
'''
2. 数组与数组的运算
数组与数组的运算,两个数组必须有相同的形状,对应位置的元素进行运算后的结果,再组成数组返回
### 数组与数组的运算,两个数组必须有相同的形状,对应位置的元素进行运算后的结果,再组成数组返回
arr = np.array([[1, 2, 3], [4, 5, 6]]) # 初始化数组
result_plus = arr + arr # 加法, 可以用操作符
print(result_plus)
''' 可以看到就是对应位置的元素进行了加法(1+1=2,2+2=4,3+3=6,...再将结果组成数组返回)
[[ 2 4 6]
[ 8 10 12]]
'''
result_sub = arr - arr # 减法
print(result_sub)
'''
[[0 0 0]
[0 0 0]]
'''
result_multi = arr * arr # 乘法
print(result_multi)
'''
[[ 1 4 9]
[16 25 36]]
'''
result_div = arr / arr # 除法
print(result_div)
''' python3中,除法运算符"/"得到的是小数
[[ 1. 1. 1.]
[ 1. 1. 1.]]
'''
result_div += result_multi # 可以使用+= *=等赋值符号给原数组设值,但要注意数据类型和精度损失问题,有时候因为数据类型不能转换而报错
print(result_div)
'''
[[ 2. 5. 10.]
[ 17. 26. 37.]]
'''
完全不同形状的数组,不允许基本运算
### 完全不同形状的数组,不允许基本运算
arr + plus_np # 报错: operands could not be broadcast together with shapes (2,3) (3,2)
3. 扩充转换
扩充转换,当数组之间在某一维度有相同的形状时,可以进行扩充转换,再进行加减乘除等算法
### 扩充转换,当数组之间在某一维度有相同的形状时,可以进行扩充转换,再进行加减乘除等算法
a = np.array([[1,1,1],[2,2,2],[3,3,3],[4,4,4]])
b = np.array([0,1,2])
a + b #可以发现 虽然两个数组维度不一样,但是可以相加 因为b被纵向扩充到了(3,4)的形状
''' 第一行为[1,1,1] + [0,1,2], 第二行为[2,2,2] + [0,1,2] ...
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
'''
c = [[0],
[1],
[2],
[3]]
a + c # c纵向填充为(3,4)的形状
'''
array([[1, 1, 1],
[3, 3, 3],
[5, 5, 5],
[7, 7, 7]])
'''
可以用扩充转换,来转换必要格式的数组
### 可以用扩充转换,来转换必要格式的数组
m = np.array([1,2,3,4])
n = np.zeros((3,4))
rr = m + n # 转换
''' 转换为(3*4)的格式
array([[ 1., 2., 3., 4.],
[ 1., 2., 3., 4.],
[ 1., 2., 3., 4.]])
'''
十. 数组的函数运算
- 基本数学函数运算
- add() subtract() multiply() divide() mod() 对应两个数组的加减乘除和取模
- absolute() fabs() 数组元素的绝对值
- power() 第一个数组元素为底,第二个数组元素为指数进行幂运算
- exp() exp2() 以e或2为底的指数结果
- log() log2() log10() 以e、2、10为底的对数
- sqrt() square() 平方根 平方
- sin() cos() tan() 正弦、余弦、正切
- arcsin() arccos() arctan() 反正弦、反余弦、反正切
- greater(x1,x2) greater_equal(x1,x2) 比较,如果x1>x2 (x1>=x2) 则返回True 同理有less() less_equal() equal() not_equal()
- floor() ceil() trunc() 向下取整、向上取整、截掉小数点
"""数组的函数运算"""
### 基本数学函数运算
a = np.arange(4) # array([0, 1, 2, 3])
b = np.arange(4,8) # array([4, 5, 6, 7])
np.add(a, b) # array([ 4, 6, 8, 10])
np.exp(a) # 对每个元素i求e^i(e是自然常数)组成新的数组 array([ 1. , 2.71828183, 7.3890561 , 20.08553692])
'''
add() subtract() multiply() divide() mod() 对应两个数组的加减乘除和取模
absolute() fabs() 数组元素的绝对值
power() 第一个数组元素为底,第二个数组元素为指数进行幂运算
exp() exp2() 以e或2为底的指数结果
log() log2() log10() 以e、2、10为底的对数
sqrt() square() 平方根 平方
sin() cos() tan() 正弦、余弦、正切
arcsin() arccos() arctan() 反正弦、反余弦、反正切
greater(x1,x2) greater_equal(x1,x2) 比较,如果x1>x2 (x1>=x2) 则返回True 同理有less() less_equal() equal() not_equal()
floor() ceil() trunc() 向下取整、向上取整、截掉小数点
'''
2. 统计函数
- max() 最大
- min() 最小
- std() 标准差
- var() 方差
- argmin() argmax() 最小、最大值索引(平铺成一维的索引)
- cumsum() 累加和
### 统计函数
a = np.arange(12).reshape(3,4)
print(a)
'''
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
'''
a.sum() # 全部求和,本例:66
a.sum(axis=0) # 纵向求和 array([12, 15, 18, 21])
a.sum(axis=1) # 横向求和 array([ 6, 22, 38])
a.min() # 最小值
a.min(axis=0) # array([0, 1, 2, 3])
a.min(axis=1) # array([0, 4, 8])
# 累加和
a.cumsum() # array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66], dtype=int32)
a.cumsum(axis=0) # 纵向累加和
'''
array([[ 0, 1, 2, 3],
[ 4, 6, 8, 10],
[12, 15, 18, 21]], dtype=int32)
'''
a.cumsum(axis=1) # 横向累加和
'''
array([[ 0, 1, 3, 6],
[ 4, 9, 15, 22],
[ 8, 17, 27, 38]], dtype=int32)
'''
'''
max() 最大
min() 最小
std() 标准差
var() 方差
argmin() argmax() 最小、最大值索引(平铺成一维的索引)
cumsum() 累加和
'''
3. 排序
### 排序
a = np.random.rand(5) # array([ 0.28450601, 0.39208123, 0.76706749, 0.0585455 , 0.21775495])
b = np.sort(a) # array([ 0.0585455 , 0.21775495, 0.28450601, 0.39208123, 0.76706749])
a = np.random.randn(12).reshape(3, 4)
print(a)
'''
[[-1.01289904 -0.93940421 0.29553346 1.68095943]
[ 0.61732077 -1.32744617 0.00564842 -0.38529139]
[ 0.43369961 -1.39254848 -0.99564321 -0.06965223]]
'''
np.sort(a, axis=0) # 每列排序,从小到大,每行数据都被打乱了
'''
array([[-1.01289904, -1.39254848, -0.99564321, -0.38529139],
[ 0.43369961, -1.32744617, 0.00564842, -0.06965223],
[ 0.61732077, -0.93940421, 0.29553346, 1.68095943]])
'''
数组排序np.sort()也可以对一些特殊格式的元素数据进行排序,不过需要定义好dtype与order入参
### 使用关键字段进行排序
b_dtype=[('姓名','U10'),('语文',int),('数学',int),('平均',float)] # 定义符合数据格式的dtype,这里起的名字在排序时有用
b_data = [('小明', 75, 78, 0), ('小红', 90, 88, 0), ('小王', 47, 98, 0)] # 定义数据
b = np.array(b_data, dtype=b_dtype) # 创建数组
b.shape # 注意这里的形状是(3,),是一维数组
'''
array([('小明', 75, 78, 0.), ('小红', 90, 88, 0.), ('小王', 47, 98, 0.)],
dtype=[('姓名', '<U10'), ('语文', '<i4'), ('数学', '<i4'), ('平均', '<f8')])
'''
np.sort(b, order=['语文']) # 按'语文'关键字排序
'''
array([('小王', 47, 98, 0.), ('小明', 75, 78, 0.), ('小红', 90, 88, 0.)],
dtype=[('姓名', '<U10'), ('语文', '<i4'), ('数学', '<i4'), ('平均', '<f8')])
'''
4. 查找插入索引
###查找 searchsorted(array, num) array只能是一维数组
a = np.sort(np.random.randint(1,30,10)) # 生成一组有序排列的数组 array([ 2, 3, 4, 10, 11, 12, 16, 22, 23, 29])
np.searchsorted(a, 4) # 查看元素4可以插入a的位置,本例:2
np.searchsorted(a, 4, side='right') # 默认site='left' 在左方插入,设置为right,右方插入,如果有与插入相等的元素,则放在最右边,本例:3
np.searchsorted(a, 15) # 查看元素15可以插入a的位置,本例:6
np.searchsorted(a, [3,4,12,20]) # 查看列表每个元素可以插入的位置list array([1, 2, 5, 7], dtype=int64)
5. 提取满足条件的元素
### 提取元素
arr = np.arange(12).reshape(3,4)
condition = np.mod(arr, 6) != 0
np.extract(condition, arr) # 提取为True的元素 array([ 1, 2, 3, 4, 5, 7, 8, 9, 10, 11]),舍弃了能被6整除的0,6
arr[np.mod(arr, 6) != 0] # 使用布尔筛选,与上面的结果相同 array([ 1, 2, 3, 4, 5, 7, 8, 9, 10, 11])
十一. 线性代数运算
1. np.dot(a,b) 矩阵乘法运算
### 矩阵乘法运算 np.dot(a,b)
a = np.arange(12).reshape(3,4)
print(a)
'''
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
'''
b = np.arange(12).reshape(4,3)
print(b)
'''
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
'''
np.dot(a,b) # 矩阵乘法
'''
array([[ 42, 48, 54],
[114, 136, 158],
[186, 224, 262]])
'''
2. np.linalg.inv(a) 逆矩阵
### 逆矩阵
a = np.arange(1,10).reshape(3,3)
np.linalg.inv(a)
'''
array([[ 3.15251974e+15, -6.30503948e+15, 3.15251974e+15],
[ -6.30503948e+15, 1.26100790e+16, -6.30503948e+15],
[ 3.15251974e+15, -6.30503948e+15, 3.15251974e+15]])
'''
3. np.linalg.solve() 求解方程组
### 求解方程组
# 3x1 + 4x2 = 4
# 2x1 + 6x2 = 3
a_np = np.array([[3, 4],[2, 6]])
r_np = np.array([4, 3])
np.linalg.solve(a_np, r_np)
''' 求得结果如下,可验证: 3*1.2+4*0.1=4 2*1.2+6*0.1=3
array([ 1.2, 0.1])
'''
4. LA.eig() 特征值、特征向量
### 特征值、特征向量 LA.eig()
from numpy import linalg as LA
q = np.diag([1,2,3,4]) # 创建矩阵
print(q)
'''
[[1 0 0 0]
[0 2 0 0]
[0 0 3 0]
[0 0 0 4]]
'''
x, y = LA.eig(q) # 求解特征值、特征向量
print(x) # [ 1. 2. 3. 4.]
print(y)
'''
[[ 1. 0. 0. 0.]
[ 0. 1. 0. 0.]
[ 0. 0. 1. 0.]
[ 0. 0. 0. 1.]]
'''
5. np.mgrid 快速创建特定数据和格式的多维网格
### 快速创建特定数据和格式的多维网格
a = np.mgrid[1:6:1] # 一维 array([1, 2, 3, 4, 5])
part_1, part_2 = np.mgrid[1:3:1,6:9:1]
print(part_1)
''' 分两部分,每个部分的shape都是(3-1,9-6)=(2,3),第一个部分纵向填充1,2,第二部部分横向填充6,7,8
[[1 1 1]
[2 2 2]]
'''
print(part_2)
'''
[[6 7 8]
[6 7 8]]
'''
b = np.mgrid[1:3:1,6:9:1] # 也可以总返回
print(b)
'''
[[[1 1 1]
[2 2 2]]
[[6 7 8]
[6 7 8]]]
'''
# 可以利用这些数据再进行计算分析,或者自造数据
(np.cos(part_1) + np.sqrt(part_2))* np.log(part_2)
'''
array([[ 5.35698821, 6.19977407, 7.00507592],
[ 3.64326141, 4.33860998, 5.01619584]])
'''
6. np.meshgrid 网格数据及拼装二维坐标
## meshgrid 是另一种横纵比网格数据
nx,ny = (3,2)
#从0开始到1结束,返回一个numpy数组,nx代表数组中元素的个数
x = np.linspace(0,1,nx)
#[ 0. 0.5 1. ]
y = np.linspace(0,1,ny)
# [0. 1.]
xv,yv = np.meshgrid(x,y)
'''
xv
[[ 0. 0.5 1. ]
[ 0. 0.5 1. ]]
yv
[[ 0. 0. 0.]
[ 1. 1. 1.]]
'''
# 这种数据非常适合拼装平面坐标系
np.c_[xv.ravel(), yv.ravel()].reshape(xv.shape[0], xv.shape[1], -1)
'''array([[[ 0. , 0. ],
[ 0.5, 0. ],
[ 1. , 0. ]],
[[ 0. , 1. ],
[ 0.5, 1. ],
[ 1. , 1. ]]])
'''
十二. 储存数组数据到文件与读取操作
"""储存数组数据到文件与读取操作"""
### 储存为二进制文件,拓展名为.npy、.npz
np.save('.temp_array',a) # 储存
b = np.load('.temp_array.npy') # 读取
'''
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
'''
## 非压缩存储
a = np.arange(1,10,2) # array([1, 3, 5, 7, 9])
b = np.arange(2,11,2) # array([ 2, 4, 6, 8, 10])
np.savez('.temp_array_z',arg1=a, arg2=b) # 储存后缀名为.npz
z_load = np.load('.temp_array_z.npz') # 读文件
z_load['arg1'] # 读数据
'''
array([1, 3, 5, 7, 9])
'''
### 储存为文本文件
np.savetxt('out.txt', a, delimiter=',', fmt='%d') # 以','分隔,数据格式类似csv文件
txt_load = np.loadtxt('out.txt', delimiter=',')