任意の要素をシャッフル

numpy – Shuffling non-zero elements of each row in an array – StackOverflow

よくある勘違い.numpy.random.shuffle()(破壊的)やnumpy.random.permutation()(コピー)は軸に沿ってシャッフルする(サブ配列の順序を変更する)だけで,サブ配列の中身はシャッフルされない.
(まあ,普通はcolumn-wiseは固定でrow-wiseにシャッフルしたい場合が多いんだろうか)
(結局,ループを回すしか無いのかな)

まず,回答者のコードをみてみる.

X = np.array([[2,3,1,0], [0,0,2,1]])
for i in range(len(X)):
    idx = np.nonzero(X[i])
    X[i][idx] = np.random.permutation(X[i][idx])
X

array([[2, 3, 1, 0],
[0, 0, 1, 2]])

array([[2, 1, 3, 0],
[0, 0, 2, 1]])

array([[1, 3, 2, 0],
[0, 0, 2, 1]])

array([[2, 3, 1, 0],
[0, 0, 2, 1]])

array([[3, 2, 1, 0],
[0, 0, 2, 1]])

%%timeit
X = np.array([[2,3,1,0], [0,0,2,1]])
for i in range(len(X)):
    idx = np.nonzero(X[i])
    X[i][idx] = np.random.permutation(X[i][idx])
X

56.5 µs ± 2.28 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

 
 
 

以前の話と同様にすれば(関連),

a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])
ind = []
res = []
rres = []
for r, subli in enumerate(a.tolist()):
    for i, x in enumerate(subli):
        if x != 0:
            res.append(x)
        else:
            ind.append((i, x))
    res.sort(reverse=True)
    for i, e in ind:
        res.insert(i, e)
    rres.append(res)
    ind = []
    res = []
np.array(rres)

array([[3, 2, 1, 0],
[0, 0, 2, 1]])

%%timeit
a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])
ind = []
res = []
rres = []
for r, subli in enumerate(a.tolist()):
    for i, x in enumerate(subli):
        if x != 0:
            res.append(x)
        else:
            ind.append((i, x))
    res.sort(reverse=True)
    for i, e in ind:
        res.insert(i, e)
    rres.append(res)
    ind = []
    res = []
np.array(rres)

18.1 µs ± 3.08 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

元々,リストをターゲットにした話だったので効率は決して良くないが.これのソート部分を,シャッフルに変える.

import random

a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])
ind = []
res = []
rres = []
for r, subli in enumerate(a.tolist()):
    for i, x in enumerate(subli):
        if x != 0:
            res.append(x)
        else:
            ind.append((i, x))
    random.shuffle(res)
    for i, e in ind:
        res.insert(i, e)
    rres.append(res)
    ind = []
    res = []
np.array(rres)

array([[2, 3, 1, 0],
[0, 0, 1, 2]])

%%timeit
a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])
ind = []
res = []
rres = []
for r, subli in enumerate(a.tolist()):
    for i, x in enumerate(subli):
        if x != 0:
            res.append(x)
        else:
            ind.append((i, x))
    random.shuffle(res)
    for i, e in ind:
        res.insert(i, e)
    rres.append(res)
    ind = []
    res = []
np.array(rres)

27 µs ± 3.33 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

精々10,000行以下のデータしか無理だろうなあ.

a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])

for r in range(a.shape[0]):
    ind = a[r].nonzero()[0]
    sind = np.random.permutation(ind)
    a[r][ind] = a[r][sind]

a

array([[1, 3, 2, 0],
[0, 0, 1, 2]])

%%timeit
a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])

for r in range(a.shape[0]):
    ind = a[r].nonzero()[0]
    sind = np.random.permutation(ind)
    a[r][ind] = a[r][sind]

a

52 µs ± 1.43 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

a = np.empty([10, 10])
a[np.random.randint(0, 5, 5), np.random.randint(0, 5, 5)] = 0
%%timeit
for r in range(a.shape[0]):
    ind = a[r].nonzero()[0]
    sind = np.random.permutation(ind)
    a[r][ind] = a[r][sind]

235 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
ind = []
res = []
rres = []
for r, subli in enumerate(a.tolist()):
    for i, x in enumerate(subli):
        if x != 0:
            res.append(x)
        else:
            ind.append((i, x))
    random.shuffle(res)
    for i, e in ind:
        res.insert(i, e)
    rres.append(res)
    ind = []
    res = []
np.array(rres)

214 µs ± 9.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

a = np.empty([100, 100])
a[np.random.randint(0, 50, 50), np.random.randint(0, 50, 50)] = 0
%%timeit
for r in range(a.shape[0]):
    ind = a[r].nonzero()[0]
    sind = np.random.permutation(ind)
    a[r][ind] = a[r][sind]

664 µs ± 15 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
ind = []
res = []
rres = []
for r, subli in enumerate(a.tolist()):
    for i, x in enumerate(subli):
        if x != 0:
            res.append(x)
        else:
            ind.append((i, x))
    random.shuffle(res)
    for i, e in ind:
        res.insert(i, e)
    rres.append(res)
    ind = []
    res = []
np.array(rres)

7.82 ms ± 89.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

 
 
 
関連:
任意の要素だけソートしてそれ以外は元の位置を維持
 
 
 
 
 
 

例えば,row-wiseではなく,column-wiseにシャッフルしようと思うと,

a = np.array([[2, 3, 1, 0], [0, 0, 2, 1]])
np.random.shuffle(a.T)
a

array([[0, 2, 3, 1],
[1, 0, 0, 2]])

広告
カテゴリー: 未分類 パーマリンク

任意の要素をシャッフル への1件のフィードバック

  1. ピンバック: 2dのnumpy.ndarrayをソートするPythonicな方法 | 粉末@それは風のように (日記)

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中