python之Numpy 排序搜尋計數及集合操作

為實現自我而奮鬥發表於2020-11-11

排序搜尋計數

排序

  • numpy.sort(a[, axis=-1, kind='quicksort', order=None])
    axis:排序沿陣列的(軸)方向,0表示按行,1表示按列,None表示展開來排序,預設為-1,表示沿最後的軸排序。
    kind:排序的演算法,提供了快排’quicksort’、混排’mergesort’、堆排’heapsort’, 預設為‘quicksort’。
    order:排序的欄位名,可指定欄位排序,預設為None.
np.random.seed(20200612)
x = np.random.rand(5, 5) * 10
x = np.around(x, 2)
print(x)
# [[2.32 7.54 9.78 1.73 6.22]
#  [6.93 5.17 9.28 9.76 8.25]
#  [0.01 4.23 0.19 1.73 9.27]
#  [7.99 4.97 0.88 7.32 4.29]
#  [9.05 0.07 8.95 7.9  6.99]]

y = np.sort(x)
print(y)
# [[1.73 2.32 6.22 7.54 9.78]
#  [5.17 6.93 8.25 9.28 9.76]
#  [0.01 0.19 1.73 4.23 9.27]
#  [0.88 4.29 4.97 7.32 7.99]
#  [0.07 6.99 7.9  8.95 9.05]]

y = np.sort(x, axis=0)
print(y)
# [[0.01 0.07 0.19 1.73 4.29]
#  [2.32 4.23 0.88 1.73 6.22]
#  [6.93 4.97 8.95 7.32 6.99]
#  [7.99 5.17 9.28 7.9  8.25]
#  [9.05 7.54 9.78 9.76 9.27]]

y = np.sort(x, axis=1)
print(y)
# [[1.73 2.32 6.22 7.54 9.78]
#  [5.17 6.93 8.25 9.28 9.76]
#  [0.01 0.19 1.73 4.23 9.27]
#  [0.88 4.29 4.97 7.32 7.99]
#  [0.07 6.99 7.9  8.95 9.05]]
  • numpy.argsort(a[, axis=-1, kind='quicksort', order=None])對陣列沿給定軸執行間接排序,並使用指定排序型別返回資料的索引陣列。這個索引陣列用於構造排序後的陣列。
np.random.seed(20200612)
x = np.random.randint(0, 10, 10)
print(x)
# [6 1 8 5 5 4 1 2 9 1]

y = np.argsort(x)
print(y)
# [1 6 9 7 5 3 4 0 2 8]

print(x[y])
# [1 1 1 2 4 5 5 6 8 9]

y = np.argsort(-x)
print(y)
# [8 2 0 3 4 5 7 1 6 9]

print(x[y])
# [9 8 6 5 5 4 2 1 1 1]

  • numpy.lexsort(keys[, axis=-1])使用鍵序列執行間接穩定排序
  • 給定多個可以在電子表格中解釋為列的排序鍵,lexsort返回一個整數索引陣列,該陣列描述了按多個列排序的順序。序列中的最後一個鍵用於主排序順序,倒數第二個鍵用於輔助排序順序,依此類推。keys引數必須是可以轉換為相同形狀的陣列的物件序列。如果為keys引數提供了2D陣列,則將其行解釋為排序鍵,並根據最後一行,倒數第二行等進行排序。
    舉個例子:按照第一列的升序或降序對整體資料進行排序。
np.random.seed(20200612)
x = np.random.rand(5, 5) * 10
x = np.around(x, 2)
print(x)
# [[2.32 7.54 9.78 1.73 6.22]
#  [6.93 5.17 9.28 9.76 8.25]
#  [0.01 4.23 0.19 1.73 9.27]
#  [7.99 4.97 0.88 7.32 4.29]
#  [9.05 0.07 8.95 7.9  6.99]]

index = np.lexsort([x[:, 0]])
print(index)
# [2 0 1 3 4]

y = x[index]
print(y)
# [[0.01 4.23 0.19 1.73 9.27]
#  [2.32 7.54 9.78 1.73 6.22]
#  [6.93 5.17 9.28 9.76 8.25]
#  [7.99 4.97 0.88 7.32 4.29]
#  [9.05 0.07 8.95 7.9  6.99]]

index = np.lexsort([-1 * x[:, 0]])
print(index)
# [4 3 1 0 2]

y = x[index]
print(y)
# [[9.05 0.07 8.95 7.9  6.99]
#  [7.99 4.97 0.88 7.32 4.29]
#  [6.93 5.17 9.28 9.76 8.25]
#  [2.32 7.54 9.78 1.73 6.22]
#  [0.01 4.23 0.19 1.73 9.27]]
  • numpy.partition(a, kth, axis=-1, kind='introselect', order=None)以索引是 kth 的元素為基準,將元素分成兩部分,即大於該元素的放在其後面,小於該元素的放在其前面,這裡有點類似於快排.
  • numpy.argpartition(a, kth, axis=-1, kind='introselect', order=None)選取索引。
搜尋
  • numpy.argmax(a[, axis=None, out=None])最大值的索引
  • numpy.argmin(a[, axis=None, out=None])最小值的索引
  • numppy.nonzero(a)其值為非零元素的下標在對應軸上的值
x = np.array([[[0, 1], [1, 0]], [[0, 1], [1, 0]], [[0, 0], [1, 0]]])
print(x)
# [[[0 1]
#   [1 0]]
#
#  [[0 1]
#   [1 0]]
#
#  [[0 0]
#   [1 0]]]
print(np.shape(x))  # (3, 2, 2)
print(x.ndim)  # 3

y = np.nonzero(x)
print(np.array(y))
# [[0 0 1 1 2]
#  [0 1 0 1 1]
#  [1 0 1 0 0]]
print(np.array(y).shape)  # (3, 5)
print(np.array(y).ndim)  # 2
print(y)
# (array([0, 0, 1, 1, 2], dtype=int64), array([0, 1, 0, 1, 1], dtype=int64), array([1, 0, 1, 0, 0], dtype=int64))
print(x[np.nonzero(x)])
#[1 1 1 1 1]
  • numpy.where(condition, [x=None, y=None])滿足條件condition
x = np.arange(10)
print(x)
# [0 1 2 3 4 5 6 7 8 9]

y = np.where(x < 5, x, 10 * x)
print(y)
# [ 0  1  2  3  4 50 60 70 80 90]

x = np.array([[0, 1, 2],
              [0, 2, 4],
              [0, 3, 6]])
y = np.where(x < 4, x, -1)
print(y)
# [[ 0  1  2]
#  [ 0  2 -1]
#  [ 0  3 -1]]

只有condition,沒有x和y,則輸出滿足條件 (即非0) 元素的座標 (等價於numpy.nonzero)。這裡的座標以tuple的形式給出,通常原陣列有多少維,輸出的tuple中就包含幾個陣列,分別對應符合條件元素的各維座標。

x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y = np.where(x > 5)
print(y)
# (array([5, 6, 7], dtype=int64),)
print(x[y])
# [6 7 8]

y = np.nonzero(x > 5)
print(y)
# (array([5, 6, 7], dtype=int64),)
print(x[y])
# [6 7 8]

x = np.array([[11, 12, 13, 14, 15],
              [16, 17, 18, 19, 20],
              [21, 22, 23, 24, 25],
              [26, 27, 28, 29, 30],
              [31, 32, 33, 34, 35]])
y = np.where(x > 25)
print(y)
# (array([3, 3, 3, 3, 3, 4, 4, 4, 4, 4], dtype=int64), array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4], dtype=int64))

print(x[y])
# [26 27 28 29 30 31 32 33 34 35]

y = np.nonzero(x > 25)
print(y)
# (array([3, 3, 3, 3, 3, 4, 4, 4, 4, 4], dtype=int64), array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4], dtype=int64))
print(x[y])
# [26 27 28 29 30 31 32 33 34 35]

  • numpy.searchsorted(a, v[, side='left', sorter=None])
    a:一維輸入陣列。當sorter引數為None的時候,a必須為升序陣列;否則,sorter不能為空,存放a中元素的index,用於反映a陣列的升序排列方式。
    v:插入a陣列的值,可以為單個元素,list或者ndarray。
    side:查詢方向,當為left時,將返回第一個符合條件的元素下標;當為right時,將返回最後一個符合條件的元素下標。
    sorter:一維陣列存放a陣列元素的 index,index 對應元素為升序。
x = np.array([0, 1, 5, 9, 11, 18, 26, 33])
y = np.searchsorted(x, [-1, 0, 11, 15, 33, 35])
print(y)  # [0 0 4 5 7 8]

y = np.searchsorted(x, [-1, 0, 11, 15, 33, 35], side='right')
print(y)  # [0 1 5 5 8 8]
  • numpy.count_nonzero(a, axis=None)返回陣列中的非0元素個數。
x = np.count_nonzero(np.eye(4))
print(x)  # 4

x = np.count_nonzero([[0, 1, 7, 0, 0], [3, 0, 0, 2, 19]])
print(x)  # 5

x = np.count_nonzero([[0, 1, 7, 0, 0], [3, 0, 0, 2, 19]], axis=0)
print(x)  # [1 1 1 1 1]

x = np.count_nonzero([[0, 1, 7, 0, 0], [3, 0, 0, 2, 19]], axis=1)
print(x)  # [2 3]

集合操作

構造集合

  • numpy.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None)
    return_index=True 表示返回新列表元素在舊列表中的位置。
    return_inverse=True表示返回舊列表元素在新列表中的位置。
    return_counts=True表示返回新列表元素在舊列表中出現的次數。
x = np.array([1, 2, 6, 4, 2, 3, 2])
u, index = np.unique(x, return_inverse=True)
print(u)  # [1 2 3 4 6]
print(index)  # [0 1 4 3 1 2 1]
print(u[index])  # [1 2 6 4 2 3 2]

u, count = np.unique(x, return_counts=True)
print(u)  # [1 2 3 4 6]
print(count)  # [1 3 1 1 1]
  • numpy.in1d(ar1, ar2, assume_unique=False, invert=False)布林運算
    前面的陣列是否包含於後面的陣列,返回布林值。返回的值是針對第一個引數的陣列的,所以維數和第一個引數一致,布林值與陣列的元素位置也一一對應。
test = np.array([0, 1, 2, 5, 0])
states = [0, 2]
mask = np.in1d(test, states)
print(mask)  # [ True False  True False  True]
print(test[mask])  # [0 2 0]

mask = np.in1d(test, states, invert=True)
print(mask)  # [False  True False  True False]
print(test[mask])  # [1 5]
  • numpy.intersect1d(ar1, ar2, assume_unique=False, return_indices=False)求兩個集合的交集
import numpy as np
from functools import reduce

x = np.intersect1d([1, 3, 4, 3], [3, 1, 2, 1])
print(x)  # [1 3]

x = np.array([1, 1, 2, 3, 4])
y = np.array([2, 1, 4, 6])
xy, x_ind, y_ind = np.intersect1d(x, y, return_indices=True)
print(x_ind)  # [0 2 4]
print(y_ind)  # [1 0 2]
print(xy)  # [1 2 4]
print(x[x_ind])  # [1 2 4]
print(y[y_ind])  # [1 2 4]

x = reduce(np.intersect1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))
print(x)  # [3]
  • numpy.union1d(ar1, ar2)求兩個集合的並集
import numpy as np
from functools import reduce

x = np.union1d([-1, 0, 1], [-2, 0, 2])
print(x)  # [-2 -1  0  1  2]
x = reduce(np.union1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))
print(x)  # [1 2 3 4 6]
'''
functools.reduce(function, iterable[, initializer])
將兩個引數的 function 從左至右積累地應用到 iterable 的條目,以便將該可迭代物件縮減為單一的值。 例如,reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) 是計算 ((((1+2)+3)+4)+5) 的值。 左邊的引數 x 是積累值而右邊的引數 y 則是來自 iterable 的更新值。 如果存在可選項 initializer,它會被放在參與計算的可迭代物件的條目之前,並在可迭代物件為空時作為預設值。 如果沒有給出 initializer 並且 iterable 僅包含一個條目,則將返回第一項。

大致相當於:
def reduce(function, iterable, initializer=None):
    it = iter(iterable)
    if initializer is None:
        value = next(it)
    else:
        value = initializer
    for element in it:
        value = function(value, element)
    return value
'''
  • numpy.setdiff1d(ar1, ar2, assume_unique=False)求兩個集合的差集
a = np.array([1, 2, 3, 2, 4, 1])
b = np.array([3, 4, 5, 6])
x = np.setdiff1d(a, b)
print(x)  # [1 2]
  • setxor1d(ar1, ar2, assume_unique=False)求兩個集合的異或
a = np.array([1, 2, 3, 2, 4, 1])
b = np.array([3, 4, 5, 6])
x = np.setxor1d(a, b)
print(x)  # [1 2 5 6]

相關文章