Pythonで配列をシャッフルし、Pythonで配列アイテムの順序をランダム化します


261

Pythonで配列をシャッフルする最も簡単な方法は何ですか?


28
+1は、Pythonドキュメントの最も有用な部分を常に優れたSO Q&A形式に移行するためのものです。
charleslparker

1
元の配列を変更せずに新しいシャッフルされた配列を返すオプションはありますか?
チャーリーパーカー

5
で新しい配列(変更なし)を取得できますnew_array = random.sample( array, len(array) )
チャーリーパーカー

回答:


464
import random
random.shuffle(array)

3
元の配列を変更せずに新しいシャッフルされた配列を返すオプションはありますか?
チャーリーパーカー

@チャーリーそれは別の質問で尋ねるのが良いことでしょう。(たぶん他の誰かがすでにそれを要求しているかもしれません。)
デビッドZ

13
皮肉なことに、このページは「python shuffle array」を検索したばかりのときのGoogleのトップヒットです
Joshua Huber

2
@Charlieの人々はこれらの質問をグーグルして、スタックオーバーフローなどの場所で答えを見つけることができます。重複でない限り、リソースとしてスタックオーバーフローをオプションにすることには何の問題もありません
Matt

@javadbaそれは実際には最初の質問への回答になるはずでした。スタックオーバーフローについて質問することは、グーグルで掘り下げて見つけられても問題ありません。将来の人々が自分で掘り起こすときに、stackoverflowの答えを見つけることができます。
マット


36

sklearnを使用してこれを行う別の方法

from sklearn.utils import shuffle
X=[1,2,3]
y = ['one', 'two', 'three']
X, y = shuffle(X, y, random_state=0)
print(X)
print(y)

出力:

[2, 1, 3]
['two', 'one', 'three']

利点:マッピングを中断することなく、複数のアレイを同時にランダム化できます。そして 'random_state'は、再現可能な動作のシャッフルを制御できます。


1
おかげで、2つのアレイを一度にシャッフルすると非常に便利です。
ドミトリー

1
これを探していた、TNX!
nOp 2018年

2
これは、受け入れられた回答よりも完全であり(多くの場合より有用)
javadba

21

他の答えが最も簡単ですが、random.shuffleメソッドが実際には何も返さないのは少し面倒です-与えられたリストをソートするだけです。呼び出しをチェーンしたい場合、またはシャッフルされた配列を1行で宣言できる場合は、次のようにします。

    import random
    def my_shuffle(array):
        random.shuffle(array)
        return array

次に、次のような行を実行できます。

    for suit in my_shuffle(['hearts', 'spades', 'clubs', 'diamonds']):

7
入力を変更することで機能することを思い出させようとしているため、特に何も返しません。(これにより、メモリを節約できます。)関数は、入力を適切に変更します。
John Y

2
スタイルだと思います。個人的には、1行で記述できるため、他の方法では2〜3行かかる方法を実現できます。プログラムをできるだけ短くすることを目的とする言語は、これらの場合に渡されたオブジェクトを返す傾向がないことは、私には奇妙に思われます。入力を適切に変更するため、このバージョンの呼び出しのrandom.shuffleの呼び出しを問題なく置き換えることができます。
Mark Rhodes、

12
Pythonは実際には可能な限り簡潔になることを目指していません。Pythonは、読みやすさと表現力のバランスをとることを目的としています。非常に高級な言語であることが主な理由です。Python独自のビルトインは、通常(常にではありません)、「関数のように」(値を返しますが、副作用はありません)または「手続きのように」(副作用を介して動作し、何も返さない)ように努めています。これは、ステートメントと式の間のPythonの非常に厳密な区別と密接に関連しています。
ジョンY

いいね。コードの違いをすぐに確認できるように、名前をmy_shuffleに変更することをお勧めします。
Jabba

多分、これは時期尚早の最適化である可能性があります(それは役立つかもしれませんが、シャッフルする必要性は明示的に配列を返す必要性を必要としません)。また、shuffle(array)に続いてshuffleを使用すると、3 + n(使用回数)ではなく2行になりますが、何度も使用すると節約になると思います。この種のこと(ファントム要件や時期尚早な最適化など)を説明する素晴らしいビデオを次に示します-pyvideo.org/video/880/stop-writing-classes
アーロンニュートン

12

通常のPythonリストを処理するときrandom.shuffle()、前の回答が示すように、仕事をします。

それがに来るときしかし、ndarraynumpy.array)、random.shuffle元を破るようですndarray。次に例を示します。

import random
import numpy as np
import numpy.random

a = np.array([1,2,3,4,5,6])
a.shape = (3,2)
print a
random.shuffle(a) # a will definitely be destroyed
print a

ただ使う: np.random.shuffle(a)

のようrandom.shufflenp.random.shuffle、配列をその場でシャッフルします。


2
破壊とはどういう意味ですか?(
つまり

まあ、A = np.array(range(9))。reshape([3,3])を試してみると
Nicholas McCarthy


3

ランダムなキーで配列を並べ替えることができます

sorted(array, key = lambda x: random.random())

キーは一度だけ読み込まれるので、並べ替え中のアイテムの比較は依然として効率的です。

random.shuffle(array)Cで記述されているため、見た目は速くなります


1
これは、配列の各要素に対して新しいランダム要素を作成しますか?
javadba 2018年

@javadbaいいえ、これはランダムなインデックスで配列をソートするだけで、配列をシャッフルします
Trinh Hoang Nhu

1
申し訳ありませんが、私は多分、私が意味するものではありませんでした明確ではありませんでしたarray私は意味 Randomの要素を:すなわちで生成されるかもしれない新しいクラスのインスタンスごとに。私は実際にはわかりません:これを行うには間違った方法になるでしょう:を作成してからを呼び出す必要があります。しかし、ないように注意してくださいPythonはどのように動作しますlambdarandom.random()RandomjavaRandom rng = Random()rng.nextGaussian()random.random()
javadba

1
あなたのコードは答えとして正しいかもしれませんが、あなたのコードが何をするかを詳しく説明しますが、それはあなたの答えの質を改善することができます。記事をチェックアウト:良い回答を書くにはどうすればよいですか?
LuFFy 2018年

1

前回の返信に加えて、別の機能を紹介したいと思います。

numpy.random.shufflerandom.shuffleインプレースシャッフルも実行します。ただし、シャッフルされた配列を返す場合numpy.random.permutationは、使用する関数です。


1

使用しrandom.shuffle()たかどうかはわかりませんが、「なし」が返されるので、これを書いたので、誰かに役立つかもしれません

def shuffle(arr):
    for n in range(len(arr) - 1):
        rnd = random.randint(0, (len(arr) - 1))
        val1 = arr[rnd]
        val2 = arr[rnd - 1]

        arr[rnd - 1] = val1
        arr[rnd] = val2

    return arr

2
はい、それはNoneを返しますが、あなたは本当に、この輸入ランダムデフシャッフル(ARR)何かを返したい場合、配列は、modifedさ:random.shuffleを(ARR)リターン・編曲
user781903

0
# arr = numpy array to shuffle

def shuffle(arr):
    a = numpy.arange(len(arr))
    b = numpy.empty(1)
    for i in range(len(arr)):
        sel = numpy.random.random_integers(0, high=len(a)-1, size=1)
        b = numpy.append(b, a[sel])
        a = numpy.delete(a, sel)
    b = b[1:].astype(int)
    return arr[b]

0

random.shuffle()は繰り返しを引き起こすため、多次元配列では使用しないでください。

最初の次元に沿って配列をシャッフルしたいと想像してください。次のテスト例を作成できます。

import numpy as np
x = np.zeros((10, 2, 3))

for i in range(10):
   x[i, ...] = i*np.ones((2,3))

したがって、最初の軸に沿って、i番目の要素は、すべての要素がiに等しい2x3行列に対応します。

多次元配列に正しいシャッフル関数を使用する場合、つまりnp.random.shuffle(x)、配列は必要に応じて最初の軸に沿ってシャッフルされます。ただし、使用random.shuffle(x)すると繰り返しが発生します。len(np.unique(x))これは、シャッフル後に実行することで確認できます。これはnp.random.shuffle()、を使用しrandom.shuffle()た場合に(予想どおり)10になりますが、約5になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.