Mezcle una matriz con python, aleatorice el orden de los elementos de la matriz con python

261

¿Cuál es la forma más fácil de barajar una matriz con python?

davethegr8
fuente
28
+1 para migrar los bits más útiles de la documentación de Python al formato SO Q&A siempre superior.
charleslparker
1
¿hay alguna opción que no mute la matriz original pero devuelva una nueva matriz aleatoria?
Charlie Parker el
55
puede obtener una nueva matriz (sin modificar) con new_array = random.sample( array, len(array) ).
Charlie Parker el

Respuestas:

464
import random
random.shuffle(array)
David Z
fuente
3
¿hay alguna opción que no mute la matriz original pero devuelva una nueva matriz aleatoria?
Charlie Parker el
@Charlie Sería bueno hacer una pregunta por separado. (Tal vez alguien más ya lo ha preguntado.)
David Z
13
Irónicamente, esta página es el éxito principal en Google cuando busqué "python shuffle array"
Joshua Huber
2
@Charlie personas Google estas preguntas para que puedan encontrar respuestas a ellos en lugares como desbordamiento de pila. Mientras no sea un duplicado, no hay nada de malo en hacer que el desbordamiento de pila sea una opción como recurso
Matt
@javadba Eso fue en realidad una respuesta a la primera pregunta. No hay nada de malo en hacer preguntas sobre el desbordamiento de la pila, incluso si se puede encontrar excavando en Google. Permite que las personas futuras encuentren la respuesta en stackoverflow cuando hacen su propia excavación.
Matt
108
import random
random.shuffle(array)
Douglas Leeder
fuente
2
¿hay alguna opción que no mute la matriz original pero devuelva una nueva matriz aleatoria?
Charlie Parker el
36

Una forma alternativa de hacer esto 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)

Salida:

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

Ventaja: puede aleatorizar múltiples matrices simultáneamente sin interrumpir el mapeo. Y 'random_state' puede controlar la combinación para un comportamiento reproducible.

Qy Zuo
fuente
1
Gracias, es muy útil barajar dos matrices a la vez.
Dmitry
1
Estaba buscando esto, TNX!
NO
2
esto es más completo (y a menudo más útil) que la respuesta aceptada
javadba
21

Las otras respuestas son las más fáciles, sin embargo, es un poco molesto que el random.shufflemétodo en realidad no devuelva nada, simplemente clasifica la lista dada. Si desea encadenar llamadas o simplemente poder declarar una matriz aleatoria en una línea, puede hacer lo siguiente:

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

Entonces puedes hacer líneas como:

    for suit in my_shuffle(['hearts', 'spades', 'clubs', 'diamonds']):
Mark Rhodes
fuente
77
No devuelve nada específicamente porque está tratando de recordarle que funciona alterando la entrada en su lugar. (Esto puede ahorrar memoria). Su función también altera su entrada.
John Y
2
Supongo que es una cosa de estilo. Personalmente, prefiero el hecho de que puedo escribir una sola línea para lograr lo que de otro modo tomaría un par. Me parece extraño que un lenguaje que tiene como objetivo permitir que los programas sean lo más cortos posible no tiende a devolver el objeto pasado en estos casos. Como altera la entrada en su lugar, puede reemplazar una llamada a random.shuffle para una llamada a esta versión sin problemas.
Mark Rhodes
12
Python en realidad no pretende ser lo más breve posible. Python tiene como objetivo equilibrar la legibilidad con la expresividad. Resulta que es bastante breve, principalmente porque es un lenguaje de muy alto nivel. Propios muebles empotrados de Python normalmente (no siempre) se esfuerzan por cualquiera ser "functionlike" (devolver un valor, pero no tienen efectos secundarios) o ser "procedurelike" (operan a través de efectos secundarios, y no devuelven nada). Esto va de la mano con la distinción bastante estricta de Python entre declaraciones y expresiones.
John Y
Agradable. Sugiero cambiarle el nombre a my_shuffle para ver la diferencia en el código de inmediato.
Jabba
Tal vez, pero esto podría ser una optimización prematura (podría ser útil, pero la necesidad de barajar no requiere explícitamente la necesidad de devolver la matriz). Además, shuffle (array) seguido de algún uso de shuffle solo sería 2 líneas en lugar de 3 + n (veces el uso), aunque supongo que sería un ahorro si lo usa muchas veces. Aquí hay un gran video que analiza este tipo de cosas (por ejemplo, requisitos fantasmas y optimización prematura) - pyvideo.org/video/880/stop-writing-classes
Aaron Newton
12

Cuando se trata de listas regulares de Python, random.shuffle()hará el trabajo tal como lo muestran las respuestas anteriores.

Pero cuando se trata de ndarray( numpy.array), random.shuffleparece romper el original ndarray. Aquí hay un ejemplo:

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

Solo usa: np.random.shuffle(a)

Al igual que random.shuffle, np.random.shufflebaraja la matriz en el lugar.

Shuai Zhang
fuente
2
¿Qué significa exactamente destruido? (Quiero decir, en este contexto, no soy un ELL.)
dbliss
Bueno, si intento A = np.array (rango (9)). Remodelar ([3,3])
Nicholas McCarthy
11

En caso de que desee una nueva matriz, puede usar sample:

import random
new_array = random.sample( array, len(array) )
Charlie Parker
fuente
3

Puede ordenar su matriz con clave aleatoria

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

la clave solo se lee una vez, por lo que comparar el elemento durante la clasificación sigue siendo eficiente.

pero parece que random.shuffle(array)será más rápido ya que está escrito en C

Trinh Hoang Nhu
fuente
1
¿Esto crea un nuevo elemento aleatorio para cada elemento de la matriz?
javadba
@javadba No, esto simplemente ordena una matriz por índice aleatorio que terminará barajando la matriz
Trinh Hoang Nhu
1
Lo siento, tal vez no estaba claro, no quise decir que arrayquise decir el Randomelemento: es decir, en lambdael random.random()podría estar generando una nueva Randominstancia de clase cada vez. No estoy realmente seguro: en javaesta sería la forma incorrecta de hacerlo: debe crear un Random rng = Random()y luego invocar el rng.nextGaussian(). Pero no estoy seguro de cómo random.random()funciona Python
javadba
1
Si bien su código puede corregirse como respuesta, pero al elaborar lo que hace su código, puede mejorar la calidad de su respuesta. Consulte el artículo: ¿Cómo escribo una buena respuesta?
LuFFy
1

Además de las respuestas anteriores, me gustaría presentar otra función.

numpy.random.shuffleasí como random.shufflerealizar barajar en el lugar. Sin embargo, si desea devolver una matriz aleatoria numpy.random.permutationes la función a utilizar.

Sable
fuente
1

No sé si lo usé, random.shuffle()pero me devuelve 'Ninguno', así que escribí esto, podría ser útil para alguien

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
Jeeva
fuente
2
sí, devuelve Ninguno, pero la matriz está modificada, si realmente desea devolver algo, entonces haga esta importación aleatoria 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]
sudeep
fuente
0

Tenga en cuenta que random.shuffle()no debe usarse en matrices multidimensionales, ya que provoca repeticiones.

Imagine que desea barajar una matriz a lo largo de su primera dimensión, podemos crear el siguiente ejemplo de prueba,

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

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

de modo que a lo largo del primer eje, el elemento i-ésimo corresponde a una matriz de 2x3 donde todos los elementos son iguales a i.

Si utilizamos la función aleatoria correcta para matrices multidimensionales, es decir np.random.shuffle(x), la matriz se barajará a lo largo del primer eje según se desee. Sin embargo, el uso random.shuffle(x)causará repeticiones. Puede verificar esto ejecutando len(np.unique(x))después de barajar, lo que le da 10 (como se esperaba) con np.random.shuffle()solo alrededor de 5 cuando lo usa random.shuffle().

Nube sabia
fuente