各位客官姥爷好,欢迎回来。上节我们了解了numpy数组的属性以及浅拷贝和深拷贝,这节我们来看看数组的其他用法。 01 改变数组的维度 0. 声明一个numpy的数组 x = np.random.randint(1,10,(3,4)) x array([[6, 3, 5, 8], [7, 9, 9, 2], [7, 8, 8, 9]]) 1. 改为一维数组 这里有两种方法: 1)flatten( order='C' )方法 y = x.flatten() print(y) y[0] = 1 print(y) print(x) [6 3 5 8 7 9 9 2 7 8 8 9] [1 3 5 8 7 9 9 2 7 8 8 9] [[6 3 5 8] [7 9 9 2] [7 8 8 9]] 2)ravel([order])方法 y = x.ravel() print(y) y[0] = 1 print(y) print(x) [6 3 5 8 7 9 9 2 7 8 8 9] [1 3 5 8 7 9 9 2 7 8 8 9] [[1 3 5 8] [7 9 9 2] [7 8 8 9]] 这里特别注意,当使用ravel时,修改新对象的值,源对象的值也会改变。 2. 改为其他维数的数组 这里同样有两种方法: 1)reshape( shape , order='C' ) 方法 x = np.random.randint(1,10,(2,6)) print(x) m = x.reshape((3,4)) print(m) m[0,1] = 88 print(m) print(x) [[2 6 9 5 4 1] [4 6 1 3 4 9]] [[2 6 9 5] [4 1 4 6] [1 3 4 9]] [[ 2 88 9 5] [ 4 1 4 6] [ 1 3 4 9]] [[ 2 88 9 5 4 1] [ 4 6 1 3 4 9]] 同样,需要注意:更改新对象的元素,源对象的也会改变。 2)resize( new_shape , refcheck=True )方法 resize方法直接在源数组上更改。 x = np.random.randint(1,10,(2,6)) print(x) #在这里赋值给y,y直接返回None。 y = x.resize((3,4)) print(x) print(y) [[8 3 1 1 5 6] [6 7 9 5 2 5]] [[8 3 1 1] [5 6 6 7] [9 5 2 5]] None 02 数组索引相关 1.根据索引取值 take(indices, axis=None, out=None, mode='raise')方法 x = np.random.randint(1,10,(2,6)) print(x) y = x.take([[1,2],[7,8]]) print(y) [[4 7 9 1 9 6] [1 7 6 4 2 9]] [[7 9] [7 6]] 如果不使用axis参数的话,默认把数组展开成一维。 x = np.random.randint(1,10,(2,6)) print(x) y = x.take([[1,2],[4,5]], axis=1) print(y) [[3 2 2 3 2 5] [3 6 6 6 3 6]] [[[2 2] [2 5]] [[6 6] [3 6]]] x = np.random.randint(1,10,(2,6)) print(x) y = x.take([[1,2],[4,5]], axis=0) print(y) 更改axis=0,直接报错超出范围 IndexError: index 2 is out of bounds for size 2 可修改mode参数来避免报错,有三种可选参数:{'raise', 'wrap', 'clip'}。 --raise表示抛出异常(默认) --wrap表示索引超出范围对数据进行环绕,环绕也就是重复使用,一轮用完,第二轮接着上。 x = np.random.randint(1,10,(5,6)) print(x) y = x.take([[1,2],[4,5]], axis=0,mode='wrap') print(y) [[4 4 9 6 6 7] [1 8 6 2 6 7] [7 9 8 6 4 3] [4 3 6 5 2 6] [9 4 6 9 5 2]] [[[1 8 6 2 6 7] [7 9 8 6 4 3]] [[9 4 6 9 5 2] [4 4 9 6 6 7]]] --clip:表示超出下标的部分,全部用最后一个。 x = np.random.randint(1,10,(5,6)) print(x) y = x.take([[1,2],[4,5]], axis=0,mode='clip') print(y) [[8 9 2 3 2 2] [8 6 1 5 2 2] [7 7 1 3 4 8] [3 5 1 7 3 5] [8 4 1 6 5 1]] [[[8 6 1 5 2 2] [7 7 1 3 4 8]] [[8 4 1 6 5 1] [8 4 1 6 5 1]]] 2.根据索引替换值 put(indices, values, mode='raise')方法 x = np.random.randint(1,10,(2,6)) print(x) y = x.put([[1,2],[3,4]],-5,mode='clip') print(x) print(y) [[3 4 4 5 2 7] [3 6 5 2 6 5]] [[ 3 -5 -5 -5 -5 7] [ 3 6 5 2 6 5]] None 需要特别留意的是:这里是直接在源对象上更改,赋值的话返回的结果会是None。 要说起来从源对象上直接更改,这里也可以使用切片用法。 x = np.random.randint(1,10,(2,6)) print(x) x[0,:3:1] = 0 print(x) x[0:4:1,1] = 10 print(x) [[9 9 4 3 1 8] [5 7 1 6 4 4]] [[0 0 0 3 1 8] [5 7 1 6 4 4]] [[ 0 10 0 3 1 8] [ 5 10 1 6 4 4]] 03 数组的排序 1. 对数组进行排序 sort(axis=-1,kind=None,order=None)用法 axis默认值是-1,表示沿最后一个轴排序。 kind有{'quicksort'、'mergesort'、'heapsort'、'stable'}四种可选排序算法:quicksort快排(默认),mergesort归并排序,heapsort堆排序,stable稳定排序。 x = np.random.randint(1,10,(2,6)) print(x) y = x.sort(axis=1) print(x) print(y) [[2 2 2 8 1 1] [3 2 5 7 1 7]] [[1 1 2 2 2 8] [1 2 3 5 7 7]] None 可以看到这里同样是直接更改源对象。如果不想直接更改源对象,有什么办法吗?我们接着往下看。 2. 返回排序的索引 argsort(axis=- 1, kind=None, order=None)方法 x = np.random.randint(1,10,(2,6)) print(x) y = x.argsort() print(y) [[1 2 9 4 6 1] [2 2 4 8 4 8]] [[0 5 1 3 4 2] [0 1 2 4 3 5]] 看到这里返回的索引,是不是对我们上面的提问有了些头绪:我们前面刚好又讲过take的用法(可以根据索引返回值)。思路有了,这就开干。 x = np.random.randint(1,10,(2,6)) print(x) y = x.argsort(axis = 1) print('******') print(y) z = x.take(y,axis = 1) print('******') print(z) [[3 9 1 9 7 3] [7 6 4 8 9 4]] ****** [[2 0 5 4 1 3] [2 5 1 0 3 4]] ****** [[[1 3 3 7 9 9] [1 3 9 3 9 7]] [[4 7 4 9 6 8] [4 4 6 7 8 9]]] 但结果有点出乎意料,相当于源数组的每行都使用了索引一次。那有没有按照轴返回数组的方法呢?还真有(首先,在这里需要感谢这些numpy的开发人员,满足我们的各种需求),具体用法是: numpy.take_along_axis(arr, indices, axis) arr参数就是数组,indices就是索引,话不多说开干。 x = np.random.randint(1,10,(2,6)) print(x) y = x.argsort(axis = 1) print('******') print(y) z = np.take_along_axis(x,y,axis = 1) print('******') print(z) [[9 9 5 5 2 1] [8 7 3 2 1 7]] ****** [[5 4 2 3 0 1] [4 3 2 1 5 0]] ****** [[1 2 5 5 9 9] [1 2 3 7 7 8]] 结果正确,over! 3. 按某些序列进行排序 np.lexsort(keys, axis=- 1)方法,注意ndarray没有lexsort方法。 这里的key加s,表示可以多个,以最后一个为第一排序依据。 x = np.array([1,2,2,3,4,6,6,7]) y = np.array([9,0,3,1,2,6,5,0]) np.lexsort((y,x)) 通过结果可以看出,对x进行排序,如果x相同的部分,则以y为排序依据。 array([0, 1, 2, 3, 4, 6, 5, 7], dtype=int64) 4.搜索排序 searchsorted(v, side='left', sorter=None)方法 返回小于或等于v值的值的索引位置。 x = np.array([9,0,3,1,2,6,5,0]) x.searchsorted(3,side='right') 5 side中的right/left其实就相当于开区间还是闭区间。 以上就是本次的分享,欢迎各位客官姥爷关注我,方便您第一次时间收到【干货】! |
|