2021-03-26 python数据处理系统学习(八)数组的形状改变、ufunc广播机制、搜索排序
1、数组形状改变
1.1 reshape函数
import numpy as np
data=((1.1,1.2,1.3,1.4),(2.1,2.2,2.3,2.4),(3.1,3.2,3.3,3.4),(4.1,4.2,4.3,4.4))
arr=np.array(data)
arr.reshape(8,2)#将元素重新组合成八行两列的样子
Out[4]:
array([[1.1, 1.2],
[1.3, 1.4],
[2.1, 2.2],
[2.3, 2.4],
[3.1, 3.2],
[3.3, 3.4],
[4.1, 4.2],
[4.3, 4.4]])
但是arr的元素组没有发生改变,只是视图发生改变,可以把新的视图赋予给新的arr1
arr
Out[5]:
array([[1.1, 1.2, 1.3, 1.4],
[2.1, 2.2, 2.3, 2.4],
[3.1, 3.2, 3.3, 3.4],
[4.1, 4.2, 4.3, 4.4]])
arr.reshape(2,-1)#两行八列
Out[13]:
array([[1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4],
[3.1, 3.2, 3.3, 3.4, 4.1, 4.2, 4.3, 4.4]])
这种表达方式可以在知道行或者列的的个数的情况下表示整个元素组
还可以将元素组展开描述如下:
arr.reshape(-1)#将元素组展平
Out[14]:
array([1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4, 4.1,
4.2, 4.3, 4.4])
1.2 resize函数
resize函数不仅仅改变视图,还改变了arr本身
arr.resize(8,2)
arr
Out[6]:
array([[1.1, 1.2],
[1.3, 1.4],
[2.1, 2.2],
[2.3, 2.4],
[3.1, 3.2],
[3.3, 3.4],
[4.1, 4.2],
[4.3, 4.4]])
1.3 shape函数
arr.shape=(8,2)
arr
Out[8]:
array([[1.1, 1.2],
[1.3, 1.4],
[2.1, 2.2],
[2.3, 2.4],
[3.1, 3.2],
[3.3, 3.4],
[4.1, 4.2],
[4.3, 4.4]])
1.4 ravel函数
将数组横向降维成一维
arr.ravel()
Out[9]:
array([1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4, 4.1,
4.2, 4.3, 4.4])
将数组纵向降成一维:
arr.ravel(order='F')
Out[10]:
array([1.1, 1.3, 2.1, 2.3, 3.1, 3.3, 4.1, 4.3, 1.2, 1.4, 2.2, 2.4, 3.2,
3.4, 4.2, 4.4])
1.5 flatten函数
flatten函数的效果和ravel函数相同
arr.flatten()
Out[11]:
array([1.1, 1.2, 1.3, 1.4, 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4, 4.1,
4.2, 4.3, 4.4])
arr.flatten(order='F')
Out[12]:
array([1.1, 1.3, 2.1, 2.3, 3.1, 3.3, 4.1, 4.3, 1.2, 1.4, 2.2, 2.4, 3.2,
3.4, 4.2, 4.4])
1.6 flatten、ravel和reshape的区别
flatten:
arr.flatten()[1]=1000
arr
Out[15]:
array([[1.1, 1.2],
[1.3, 1.4],
[2.1, 2.2],
[2.3, 2.4],
[3.1, 3.2],
[3.3, 3.4],
[4.1, 4.2],
[4.3, 4.4]])
用flatten改变某一个元素的时候,原arr不发生改变
ravel:
arr.ravel()[1]=1000
arr
Out[16]:
array([[ 1.1, 1000. ],
[ 1.3, 1.4],
[ 2.1, 2.2],
[ 2.3, 2.4],
[ 3.1, 3.2],
[ 3.3, 3.4],
[ 4.1, 4.2],
[ 4.3, 4.4]])
用ravel改变某个元素时,原arr改变
reshape:
arr.reshape(-1)[3]=10
arr
Out[19]:
array([[ 1.1, 1000. ],
[ 1.3, 10. ],
[ 2.1, 2.2],
[ 2.3, 2.4],
[ 3.1, 3.2],
[ 3.3, 3.4],
[ 4.1, 4.2],
[ 4.3, 4.4]])
reshape函数作用后,原arr改变
但是这三种都不会改变原数组的形状
此外,数组形状的判断不能靠眼睛,要用以下几种方法:
att_t=arr.ravel()
att_t.ndim
Out[21]: 1
att_t.shape
Out[22]: (16,)
1.7增加一个维度
att_t[np.newaxis,:]#增加行向量
Out[23]:
array([[ 1.1, 1000. , 1.3, 10. , 2.1, 2.2, 2.3, 2.4,
3.1, 3.2, 3.3, 3.4, 4.1, 4.2, 4.3, 4.4]])
att_t[:,np.newaxis]#增加列向量
Out[24]:
array([[ 1.1],
[1000. ],
[ 1.3],
[ 10. ],
[ 2.1],
[ 2.2],
[ 2.3],
[ 2.4],
[ 3.1],
[ 3.2],
[ 3.3],
[ 3.4],
[ 4.1],
[ 4.2],
[ 4.3],
[ 4.4]])
att_t[:,np.newaxis].ndim#增加列向量
Out[26]: 2
att_t[:,np.newaxis].shape#增加列向量
Out[27]: (16, 1)
1.8将两个数组合并
1.8.1 横向合并
arr1=np.arange(12).reshape(3,4)
arr1
Out[31]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
arr2=([[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4]])
arr2
Out[32]: [[1.1, 1.2, 1.3, 1.4], [2.1, 2.2, 2.3, 2.4], [3.1, 3.2, 3.3, 3.4]]
np.hstack((arr1,arr2))
Out[33]:
array([[ 0. , 1. , 2. , 3. , 1.1, 1.2, 1.3, 1.4],
[ 4. , 5. , 6. , 7. , 2.1, 2.2, 2.3, 2.4],
[ 8. , 9. , 10. , 11. , 3.1, 3.2, 3.3, 3.4]])
np.hstack((arr1,arr2)).shape
Out[34]: (3, 8)
1.8.2 纵向合并
np.vstack((arr1,arr2))
Out[36]:
array([[ 0. , 1. , 2. , 3. ],
[ 4. , 5. , 6. , 7. ],
[ 8. , 9. , 10. , 11. ],
[ 1.1, 1.2, 1.3, 1.4],
[ 2.1, 2.2, 2.3, 2.4],
[ 3.1, 3.2, 3.3, 3.4]])
np.vstack((arr1,arr2)).shape
Out[37]: (6, 4)
1.8.3 concatenate拼接
需要指定拼接的方向,对0轴的数组对象进行纵向的拼接(纵向的拼接沿着axis= 1方向);注:默认axis = 0,就是对该轴向的数组进行操作,操作方向是另外一个轴,即axis=1。
np.concatenate((arr1,arr2),axis=1)
Out[38]:
array([[ 0. , 1. , 2. , 3. , 1.1, 1.2, 1.3, 1.4],
[ 4. , 5. , 6. , 7. , 2.1, 2.2, 2.3, 2.4],
[ 8. , 9. , 10. , 11. , 3.1, 3.2, 3.3, 3.4]])
np.concatenate((arr1,arr2),axis=0)
Out[39]:
array([[ 0. , 1. , 2. , 3. ],
[ 4. , 5. , 6. , 7. ],
[ 8. , 9. , 10. , 11. ],
[ 1.1, 1.2, 1.3, 1.4],
[ 2.1, 2.2, 2.3, 2.4],
[ 3.1, 3.2, 3.3, 3.4]])
1.9复制
tile函数可以将原有的数组进行复制,复制成x行y列的大数组
arr3=np.array([[0,1],[2,3]])
np.tile(arr3,(3,4))
Out[42]:
array([[0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3],
[0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3],
[0, 1, 0, 1, 0, 1, 0, 1],
[2, 3, 2, 3, 2, 3, 2, 3]])
np.tile(arr3,(3,4)).shape
Out[43]: (6, 8)
1.10 多维数组
可以根据方括号的数量来判断这是几维数组
arr4=np.arange(8).reshape(2,2,2)
arr4
Out[46]:
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
arr4.ndim
Out[47]: 3
arr4.shape
Out[48]: (2, 2, 2)
2、数组的ufunc广播机制
2.1 数组进行相加
arr1=([[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4]])
arr2=np.arange(12).reshape(3,4)
arr1+arr2
Out[50]:
array([[ 1.1, 2.2, 3.3, 4.4],
[ 6.1, 7.2, 8.3, 9.4],
[11.1, 12.2, 13.3, 14.4]])
即使维度不同也能进行运算:
arr3=np.array([1,2,3,4])
arr1+arr3
Out[53]:
array([[2.1, 3.2, 4.3, 5.4],
[3.1, 4.2, 5.3, 6.4],
[4.1, 5.2, 6.3, 7.4]])
这是因为不同数组进行加和的话则会执行广播机制,即自己进行补齐(以下是行的补齐方式):
1 | 2 | 3 | 4 |
---|
会自己补齐成
1 | 2 | 3 | 4 |
---|---|---|---|
1 | 2 | 3 | 4 |
1 | 2 | 3 | 4 |
然后参与到运算中(按列的话也是以相同的方式复制)
只有行数是相等的或者列数是相等的时候才能运用这个广播机制
2.2 运算
math=np.array([98,97,93,94])
english=np.array([93,92,91,90])
chinese=np.array([94,95,96,97])
total=math+english+chinese
total
Out[55]: array([285, 284, 280, 281])
np.add(math,np.add(chinese,english))
Out[56]: array([285, 284, 280, 281])
np.subtract(math,english)#减法
Out[57]: array([5, 5, 2, 4])
2.3集合
2.3.1找出所有元素,并以出现一次的模式呈现
s=np.array([1,2,3,4,5,1,2,3,4,5,7,8,9])
np.unique(s)#找出所有元素
Out[58]: array([1, 2, 3, 4, 5, 7, 8, 9])
2.3.2 判断集合的元素是否在另一个集合中
test=[1,2,3]
np.in1d(s,test)#判断s是否在test里
Out[62]:
array([ True, True, True, False, False, True, True, True, False,
False, False, False, False])
2.3.3找出交集
np.intersect1d(s,test)
Out[63]: array([1, 2, 3])
2.4 比较运算
2.4.1 判断是否相等
arr1=([[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4]])
arr2=np.array([1,2,3,4])
arr1==arr2
Out[64]:
array([[False, False, False, False],
[False, False, False, False],
[False, False, False, False]])
另一种方式:
np.equal(arr1,arr2)
Out[65]:
array([[False, False, False, False],
[False, False, False, False],
[False, False, False, False]])
2.4.2 比大小
np.greater(arr1,arr2)
Out[66]:
array([[ True, False, False, False],
[ True, True, False, False],
[ True, True, True, False]])
arr1>arr2
Out[67]:
array([[ True, False, False, False],
[ True, True, False, False],
[ True, True, True, False]])
np.greater(arr1,arr2).all()
Out[68]: False
2.4.3 判断是否有数值
s1=np.array([1,-1,np.nan])
np.isnan(s1)
Out[69]: array([False, False, True])
3、搜索与排序
返回排序结果:
s=np.array([1,-1,2,3,7,4,6,9,6])
np.sort(s)
Out[70]: array([-1, 1, 2, 3, 4, 6, 6, 7, 9])
返回列表的排序结果:
sorted(s)
Out[71]: [-1, 1, 2, 3, 4, 6, 6, 7, 9]
降序返回列表:
sorted(s,reverse=True)
Out[72]: [9, 7, 6, 6, 4, 3, 2, 1, -1]
降序返回数组:
np.array(sorted(s,reverse=True))
Out[73]: array([ 9, 7, 6, 6, 4, 3, 2, 1, -1])
返回索引位置:
np.argsort(s)
Out[74]: array([1, 0, 2, 3, 5, 6, 8, 4, 7], dtype=int64)
返回最大数的索引:
s.argmax()
Out[75]: 7
分别返回数组里的最大值和最大值的索引
arr1=np.array([[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4]])
arr1.max(axis=0)
Out[79]: array([3.1, 3.2, 3.3, 3.4])
arr1.argmax(axis=0)
Out[80]: array([2, 2, 2, 2], dtype=int64)
与某个数值判断大小,并返回想要的数值
arr1=np.array([[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4]])
np.where(arr1>2.2,'1','0')
Out[81]:
array([['0', '0', '0', '0'],
['0', '0', '1', '1'],
['1', '1', '1', '1']], dtype='<U1')
与某个数组判断大小,并返回想要的数值
arr1=np.array([[1.1,1.2,1.3,1.4],[2.1,2.2,2.3,2.4],[3.1,3.2,3.3,3.4]])
arr2=np.array([1,2,3,4])
np.where(arr1>arr2,'1','0')
Out[82]:
array([['1', '0', '0', '0'],
['1', '1', '0', '0'],
['1', '1', '1', '0']], dtype='<U1')
提取满足某一特定条件的值
np.extract(arr1>arr2,arr1)
Out[83]: array([1.1, 2.1, 2.2, 3.1, 3.2, 3.3])