Mescola un array con Python, randomizza l'ordine degli elementi dell'array con Python


261

Qual è il modo più semplice per mescolare un array con Python?


28
+1 per la migrazione dei bit più utili della documentazione di Python nel formato di domande e risposte SO sempre superiore.
charleslparker,

1
esiste un'opzione che non muta l'array originale ma restituisce un nuovo array mischiato?
Charlie Parker,

5
puoi ottenere un nuovo array (non modificato) con new_array = random.sample( array, len(array) ).
Charlie Parker,

Risposte:


464
import random
random.shuffle(array)

3
esiste un'opzione che non muta l'array originale ma restituisce un nuovo array mischiato?
Charlie Parker,

@Charlie Sarebbe una buona cosa porre una domanda separata. (Forse qualcun altro l'ha già chiesto.)
David Z,

13
Per ironia della sorte, questa pagina è il massimo successo in Google quando ho appena cercato "Python shuffle array"
Joshua Huber,

2
@Charlie persone Google queste domande in modo che possano trovare le risposte in luoghi come lo overflow dello stack. Finché non è un duplicato, non c'è niente di sbagliato nel rendere lo stack overflow un'opzione come risorsa
Matt

@javadba Questo doveva essere una risposta alla prima domanda. Non c'è niente di sbagliato nel porre domande sullo overflow dello stack anche se potrebbe essere trovato con qualche scavo su Google. Consente alle persone future di trovare la risposta su StackOverflow quando eseguono le proprie ricerche.
Matt,


36

Modo alternativo per farlo usando 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)

Produzione:

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

Vantaggio: è possibile eseguire casualmente più array contemporaneamente senza interrompere la mappatura. E 'random_state' può controllare lo shuffle per comportamenti riproducibili.


1
Grazie, è molto utile mescolare due array contemporaneamente.
Dmitry il

1
Stavo cercando questo, TNX!
dal

2
questo è più completo (e spesso più utile) della risposta accettata
javadba,

21

Le altre risposte sono le più semplici, tuttavia è un po 'fastidioso che il random.shufflemetodo in realtà non restituisca nulla, ma ordina semplicemente l'elenco fornito. Se vuoi concatenare le chiamate o essere in grado di dichiarare un array mischiato su una linea puoi fare:

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

Quindi puoi fare linee come:

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

7
Non restituisce nulla in particolare perché sta cercando di ricordare che funziona modificando l'input sul posto. (Questo può risparmiare memoria.) La tua funzione modifica anche il suo ingresso in posizione.
John Y,

2
Immagino sia una cosa di stile. Personalmente preferisco il fatto di poter scrivere una sola riga per ottenere ciò che altrimenti richiederebbe una coppia. Mi sembra strano che una lingua che mira a consentire ai programmi di essere il più brevi possibile in questi casi non tenda a restituire l'oggetto passato. Poiché altera l'input in atto, è possibile sostituire una chiamata a random.shuffle per una chiamata a questa versione senza problemi.
Mark Rhodes,

12
Python in realtà non mira ad essere il più breve possibile. Python mira a bilanciare la leggibilità con l'espressività. Capita quindi di essere abbastanza breve, principalmente perché è un linguaggio di alto livello. Proprio built-in di Python in genere (non sempre) si sforzano di entrambi essere "functionlike" (restituire un valore, ma non hanno effetti collaterali) o essere "procedurelike" (operano attraverso gli effetti collaterali, e non restituiscono nulla). Questo va di pari passo con la distinzione abbastanza rigorosa di Python tra affermazioni ed espressioni.
John Y,

Bello. Suggerisco di rinominarlo in my_shuffle per vedere immediatamente la differenza nel codice.
Jabba,

Forse, ma potrebbe trattarsi di un'ottimizzazione prematura (potrebbe essere utile, ma la necessità di shuffle non richiede esplicitamente la necessità di restituire l'array). Inoltre, shuffle (array) seguito da un certo uso di shuffle sarebbero solo 2 righe invece di 3 + n (tempi di utilizzo), anche se immagino che sarebbe un risparmio se lo usi più volte. Ecco un ottimo video che discute questo tipo di cose (ad esempio requisiti fantasma e ottimizzazione prematura) - pyvideo.org/video/880/stop-writing-classes
Aaron Newton

12

Quando si ha a che fare con elenchi Python regolari, random.shuffle()farà il lavoro proprio come mostrano le risposte precedenti.

Ma quando si tratta di ndarray( numpy.array), random.shufflesembra rompere l'originale ndarray. Ecco un esempio:

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

Usa solo: np.random.shuffle(a)

Ad esempio random.shuffle, np.random.shufflemescola l'array sul posto.


2
cosa significa esattamente distrutto? (Voglio dire, in questo contesto - non sono un ELL.)
bliss il

Bene, se provo A = np.array (range (9)). Reshape ([3,3])
Nicholas McCarthy,

11

Nel caso in cui desideri un nuovo array puoi usare sample:

import random
new_array = random.sample( array, len(array) )

3

È possibile ordinare l'array con chiave casuale

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

la chiave deve essere letta una sola volta, quindi confrontando l'elemento durante l'ordinamento è ancora efficiente.

ma sembra che random.shuffle(array)sarà più veloce da quando è scritto in C


1
questo crea un nuovo elemento casuale per ogni elemento dell'array?
Javavba,

@javadba No, basta ordinare un array per indice casuale che finirà per mescolare l'array
Trinh Hoang Nhu

1
Mi dispiace, forse non ero chiaro, non arrayintendevo l' Randomelemento intendo l' elemento: vale a dire in lambdathe random.random()potrebbe essere la generazione di nuove Randomistanze di classe ogni volta. In realtà non sono sicuro: in javaquesto sarebbe il modo sbagliato di farlo: dovresti creare un Random rng = Random()e quindi invocare il rng.nextGaussian(). Ma non è sicuro come python random.random()funziona
javadba

1
Mentre il tuo codice può essere corretto come risposta Ma elaborando ciò che fa il tuo codice, può migliorare la qualità della tua risposta. Leggi l'articolo: come posso scrivere una buona risposta?
LuFFy,

1

Oltre alle risposte precedenti, vorrei introdurre un'altra funzione.

numpy.random.shuffleoltre a random.shuffleeseguire lo shuffling sul posto. Tuttavia, se si desidera restituire un array mischiato numpy.random.permutationè la funzione da utilizzare.


1

Non so di averlo usato random.shuffle()ma mi restituisce "Nessuno", quindi ho scritto questo, potrebbe essere utile a qualcuno

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
sì restituisce Nessuno, ma l'array viene modificato, se si desidera veramente restituire qualcosa, eseguire l'importazione random def shuffle (arr): random.shuffle (arr) return 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

Fai attenzione a random.shuffle() non deve essere utilizzato su array multidimensionali poiché causa ripetizioni.

Immagina di voler mescolare un array lungo la sua prima dimensione, possiamo creare il seguente esempio di test,

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

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

in modo che lungo il primo asse, l'elemento i-esimo corrisponda a una matrice 2x3 in cui tutti gli elementi sono uguali a i.

Se utilizziamo la corretta funzione shuffle per array multidimensionali, ovvero np.random.shuffle(x)l'array verrà mischiato lungo il primo asse come desiderato. Tuttavia, l'utilizzo random.shuffle(x)provocherà ripetizioni. Puoi verificarlo eseguendolo len(np.unique(x))dopo averlo mischiato che ti dà 10 (come previsto) con np.random.shuffle()ma solo circa 5 quando lo usi random.shuffle().

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.