python numpy在保持行的整體性的情況下按列排序
阿新 • • 發佈:2018-12-22
某公司的資料日常處理。看著規整的資料我就想到了numpy。
這是資料:
>>>> a
array([[ 2, 7, 1, 2],
[35, 9, 1, 2],
[22, 12, 4, 2]])
>>>
按照第一列排序,想要變成這樣的效果:
>>> a
array([[ 2, 7, 1, 2],
[22, 12, 4, 2],
[35, 9, 1, 2]])
>>>
行的整體性並沒有被破壞。
開寫:
# -*- coding: cp936 -*- import numpy as np import pprint a = np.array( [[ 2, 7, 1, 2], [ 35, 9, 1, 2], [ 22, 12, 4, 2]] ) a1 = a[:,::-1].T a2 = np.lexsort(a1) a3 = a[a2] pprint.pprint(a3)
好吧,就3行,開始寫註釋吧,不然自己都會忘了(不可能,我這麼帥,怎麼可能忘記)
a1 = a[:,::-1].T
註釋:#先逆序再轉置
#逆序結果:
#[2,1,7,2]
#[2,1,9,35]
#[2,4,12,22]
#轉置結果:
#[2,2,2]
#[1,1,4]
#[7,9,12]
#[2,35,22]
a2 = np.lexsort(a1)
註釋:#np.lexsort(),以列為整體性進行排序,重點是:從最後一行開始比較大小,正因為從最後一行開始排序,前面才用逆序 #排序結果: #[0 2 1] #0表示,排序後的第1列在a1的第0列,[2,1,7,2] #2表示,排序後的第2列在a1的第2列,[2,4,12,22] #1表示,排序後的第3列在a1的第1列,[2,1,9,35]
a3 = a[a2]
註釋:#拿著新的序列號[0 2 1],調整下a就是我們要的結果了
好了,思考下,如果按第二列排序怎麼辦?
Ps:之前的資料本來排好序了,更換下資料。
開寫:
結果:# -*- coding: cp936 -*- import numpy as np from numpy import * import pprint a = np.array( [[ 2, 77, 1, 2], [ 35, 9, 1, 2], [ 22, 12, 4, 2]] ) print '排序前:' pprint.pprint(a) a1 = a.T a2 = a1[array([0,3,2,1])] #2列換到最後列(因為轉置,此時應該說2行換最後行) a3 = np.lexsort(a2) a4 = a[a3] print '排序後:' pprint.pprint(a4)
>>>
排序前:
array([[ 2, 77, 1, 2],
[35, 9, 1, 2],
[22, 12, 4, 2]])
排序後:
array([[35, 9, 1, 2],
[22, 12, 4, 2],
[ 2, 77, 1, 2]])
>>>
其實就是把第2列換到最後一列,然後重複之前的操作。
好吧,思考下,按照任意列排序,怎麼搞?
輸入引數:col_index(0,1,2,3...)表示按照第col_index列排序。
分析:因為轉置的原因,題目要求等價於按照轉置後的第col_index行排序。
這個還真有點意思,因為coding的時候,要把第col_index行和最後一行互換,不知道怎麼寫這個:
if col_index = 0: a2 = a1[array([3,1,2,col_index])]
if col_index = 1: a2 = a1[array([0,3,2,col_index])]
if col_index = 2: a2 = a1[array([0,1,3,col_index])]
if col_index = 3: a2 = a1[array([0,1,2,col_index])]
我可不想用100個if來表示100列。
動態生成?不可能,我肯定避開不了做判斷的時候。
算了,既然資料保證了每一行格式都是規整的,直接兩行交換吧。numpy做兩行運算還是挺快的。
交換a,b :a = a + b, b = a - b, a = a- b。
# -*- coding: cp936 -*-
import numpy as np
from numpy import *
import pprint
a = np.array(
[[ 2, 77, 1, 2],
[ 35, 9, 1, 2],
[ 22, 12, 4, 2]]
)
print '排序前:'
pprint.pprint(a)
def sort_by_col(a,col_index):
a1 = a.T
col_max = a.shape[-1]-1
if col_index < col_max:
#兩行互換
a1[col_index] = a1[col_index] + a1[col_max]
a1[col_max] = a1[col_index] - a1[col_max]
a1[col_index] = a1[col_index] - a1[col_max]
a2 = np.lexsort(a1)
#因為a1的行交換影響了a(雖然id不同,但是是同一片記憶體),得到序列結果後再換回來,保持a的純潔
a1[col_index] = a1[col_index] + a1[col_max]
a1[col_max] = a1[col_index] - a1[col_max]
a1[col_index] = a1[col_index] - a1[col_max]
else:
a2 = np.lexsort(a1)
return a[a2]
for i in range(4):
col_index = i
a = sort_by_col(a,col_index)
print '當col_index = %d ,排序後:' % col_index
pprint.pprint(a)
結果:
>>>
排序前:
array([[ 2, 77, 1, 2],
[35, 9, 1, 2],
[22, 12, 4, 2]])
當col_index = 0 ,排序後:
array([[ 2, 77, 1, 2],
[22, 12, 4, 2],
[35, 9, 1, 2]])
當col_index = 1 ,排序後:
array([[35, 9, 1, 2],
[22, 12, 4, 2],
[ 2, 77, 1, 2]])
當col_index = 2 ,排序後:
array([[35, 9, 1, 2],
[ 2, 77, 1, 2],
[22, 12, 4, 2]])
當col_index = 3 ,排序後:
array([[35, 9, 1, 2],
[ 2, 77, 1, 2],
[22, 12, 4, 2]])
>>>