簡體   English   中英

隨機打亂numpy數組每行中的項目

[英]Randomly shuffle items in each row of numpy array

我有一個如下的numpy數組:

Xtrain = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [1, 7, 3]])

我想分別洗牌每行的項目,但不希望每行的洗牌都相同(在幾個例子中只是洗牌列順序)。

例如,我想要如下輸出:

output = np.array([[3, 2, 1],
                   [4, 6, 5],
                   [7, 3, 1]])

如何以有效的方式隨機隨機打亂每一行? 我的實際 np 數組超過 100000 行和 1000 列。

由於您只想對列進行洗牌,因此您可以對矩陣的轉置執行洗牌

In [86]: np.random.shuffle(Xtrain.T)

In [87]: Xtrain
Out[87]: 
array([[2, 3, 1],
       [5, 6, 4],
       [7, 3, 1]])

請注意,二維數組上的random.suffle()會隨機播放行而不是每行中的項目。 即改變行的位置。 因此,如果您更改轉置矩陣行的位置,您實際上是在改組原始數組的列。

如果您仍然想要一個完全獨立的隨機播放,您可以為每一行創建隨機索引,然后使用簡單的索引創建最終數組:

In [172]: def crazyshuffle(arr):
     ...:     x, y = arr.shape
     ...:     rows = np.indices((x,y))[0]
     ...:     cols = [np.random.permutation(y) for _ in range(x)]
     ...:     return arr[rows, cols]
     ...: 

演示:

In [173]: crazyshuffle(Xtrain)
Out[173]: 
array([[1, 3, 2],
       [6, 5, 4],
       [7, 3, 1]])

In [174]: crazyshuffle(Xtrain)
Out[174]: 
array([[2, 3, 1],
       [4, 6, 5],
       [1, 3, 7]])

來自: https ://github.com/numpy/numpy/issues/5173

def disarrange(a, axis=-1):
    """
    Shuffle `a` in-place along the given axis.

    Apply numpy.random.shuffle to the given axis of `a`.
    Each one-dimensional slice is shuffled independently.
    """
    b = a.swapaxes(axis, -1)
    # Shuffle `b` in-place along the last axis.  `b` is a view of `a`,
    # so `a` is shuffled in place, too.
    shp = b.shape[:-1]
    for ndx in np.ndindex(shp):
        np.random.shuffle(b[ndx])
    return

這個解決方案無論如何都不是有效的,但我覺得它很有趣,所以把它寫下來。 基本上,你解開數組,並創建一個行標簽數組和一個索引數組。 您打亂索引數組,並用它索引原始和行標簽數組。 然后,您將穩定的 argsort 應用於行標簽以將數據收集到行中。 應用該索引並重塑和中提琴,數據按行獨立打亂:

import numpy as np

r, c = 3, 4  # x.shape

x = np.arange(12) + 1  # Already raveled 
inds = np.arange(x.size)
rows = np.repeat(np.arange(r).reshape(-1, 1), c, axis=1).ravel()

np.random.shuffle(inds)
x = x[inds]
rows = rows[inds]

inds = np.argsort(rows, kind='mergesort')
x = x[inds].reshape(r, c)

這是一個IDEOne 鏈接

我們可以創建一個隨機的二維矩陣,按每一行排序,然后使用argsort給出的索引矩陣對目標矩陣進行重新排序。

target = np.random.randint(10, size=(5, 5))
# [[7 4 0 2 5]
# [5 6 4 8 7]
# [6 4 7 9 5]
# [8 6 6 2 8]
# [8 1 6 7 3]]

shuffle_helper = np.argsort(np.random.rand(5,5), axis=1)
# [[0 4 3 2 1]
# [4 2 1 3 0]
# [1 2 3 4 0]
# [1 2 4 3 0]
# [1 2 3 0 4]]

target[np.arange(shuffle_helper.shape[0])[:, None], shuffle_helper]
# array([[7, 5, 2, 0, 4],
#       [7, 4, 6, 8, 5],
#       [4, 7, 9, 5, 6],
#       [6, 6, 8, 2, 8],
#       [1, 6, 7, 8, 3]])

解釋

  • 我們使用np.random.randargsort來模擬洗牌的效果。
  • random.rand給出隨機性。
  • 然后,我們使用argsortaxis=1來幫助對每一行進行排名。 這將創建可用於重新排序的索引。

假設您有a形狀為 100000 x 1000 的數組。

b = np.random.choice(100000 * 1000, (100000, 1000), replace=False)
ind = np.argsort(b, axis=1)
a_shuffled = a[np.arange(100000)[:,np.newaxis], ind]

我不知道這是否比循環快,因為它需要排序,但是使用此解決方案也許您會發明更好的東西,例如使用np.argpartition而不是np.argsort

你可以使用Pandas

df = pd.DataFrame(X_train)
_ = df.apply(lambda x: np.random.permutation(x), axis=1, raw=True)
df.values

如果要隨機排列列,請將關鍵字更改為axis=0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM