Embaralhe uma matriz com python, randomize a ordem dos itens da matriz com python

261

Qual é a maneira mais fácil de embaralhar uma matriz com python?

davethegr8
fonte
28
+1 para migrar os bits mais úteis da documentação do python para o sempre superior formato de perguntas e respostas SO.
charleslparker
1
existe uma opção que não modifique a matriz original, mas retorne uma nova matriz aleatória?
Charlie Parker
5
você pode obter uma nova matriz (não modificada) com new_array = random.sample( array, len(array) ).
Charlie Parker

Respostas:

464
import random
random.shuffle(array)
David Z
fonte
3
existe uma opção que não modifique a matriz original, mas retorne uma nova matriz aleatória?
Charlie Parker
@ Charlie Isso seria uma boa coisa para fazer em uma pergunta separada. (Talvez alguém já perguntou isso.)
David Z
13
Ironicamente, esta página é o hit no topo do Google quando eu só procurou "array shuffle python"
Joshua Huber
2
As pessoas @Charlie pesquisam no Google essas perguntas para encontrar respostas em lugares como estouro de pilha. Enquanto isso não é uma duplicata não há nada de errado em fazer stack overflow uma opção como um recurso
Matt
@ javadba Na verdade, era para ser uma resposta à primeira pergunta. Não há nada de errado em fazer perguntas sobre o estouro de pilha, mesmo que isso possa ser encontrado com algumas escavações no google. Ele permite que futuras pessoas encontrem a resposta no stackoverflow quando fizerem suas próprias escavações.
Matt
108
import random
random.shuffle(array)
Douglas Leeder
fonte
2
existe uma opção que não modifique a matriz original, mas retorne uma nova matriz aleatória?
Charlie Parker
36

Maneira alternativa de fazer isso usando o 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)

Resultado:

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

Vantagem: você pode aleatoriamente várias matrizes simultaneamente sem interromper o mapeamento. E 'random_state' pode controlar a reprodução aleatória de comportamentos reproduzíveis.

Qy Zuo
fonte
1
Obrigado, é muito útil embaralhar duas matrizes ao mesmo tempo.
Dmitry
1
Estava procurando por isso, TNX!
NOP
2
este é mais completa (e muitas vezes mais útil) do que a resposta aceita
javadba
21

As outras respostas são as mais fáceis, no entanto, é um pouco chato que o random.shufflemétodo não retorne nada - apenas classifica a lista fornecida. Se você deseja encadear chamadas ou apenas poder declarar uma matriz embaralhada em uma linha, você pode:

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

Então você pode fazer linhas como:

    for suit in my_shuffle(['hearts', 'spades', 'clubs', 'diamonds']):
Mark Rhodes
fonte
7
Ele não retorna nada especificamente porque está tentando lembrá-lo de que funciona alterando a entrada no local. (Isso pode economizar memória.) Sua função também altera sua entrada.
John Y
2
Eu acho que é uma coisa de estilo. Pessoalmente, prefiro o fato de poder escrever uma única linha para alcançar o que seria necessário em alguns casos. Parece-me estranho que uma linguagem que visa permitir que os programas sejam o mais curtos possível, não tende a retornar o objeto passado nesses casos. Como altera a entrada no local, você pode substituir uma chamada para random.shuffle por uma chamada para esta versão sem problemas.
Mark Rhodes
12
O Python não tem como objetivo ser o mais breve possível. O Python visa equilibrar legibilidade com expressividade. Por isso, é bastante breve, principalmente porque é uma linguagem de nível muito alto. Próprios built-ins do Python normalmente (não sempre) se esforçam para tanto ser "functionlike" (retornar um valor, mas não têm efeitos colaterais) ou ser "procedurelike" (operar através de efeitos colaterais, e não retornar nada). Isso anda de mãos dadas com a distinção bastante estrita do Python entre declarações e expressões.
John Y
Agradável. Sugiro renomeá-lo para my_shuffle para ver a diferença no código imediatamente.
Jabba
Talvez, mas isso pode ser uma otimização prematura (pode ser útil, mas a necessidade de embaralhar não exige explicitamente a necessidade de retornar a matriz). Além disso, shuffle (array) seguido de algum uso de shuffle seria apenas 2 linhas em oposição a 3 + n (vezes o uso), embora eu ache que seria uma economia se você o usar muitas vezes. Aqui está um ótimo vídeo que discute este tipo de coisa (por exemplo, requisitos fantasmas e otimização prematura) - pyvideo.org/video/880/stop-writing-classes
Aaron Newton
12

Ao lidar com listas regulares de Python, random.shuffle()fará o trabalho exatamente como as respostas anteriores mostram.

Mas quando se trata de ndarray( numpy.array), random.shuffleparece quebrar o original ndarray. Aqui está um exemplo:

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

Apenas use: np.random.shuffle(a)

Como random.shuffle, np.random.shuffleembaralha a matriz no local.

Shuai Zhang
fonte
2
o que significa exatamente destruído? (i significa, neste contexto - Eu não sou um ELL.)
dbliss
. Bem, se eu tento A = np.array (intervalo (9)) remodelagem ([3,3])
Nicholas McCarthy
11

Caso queira uma nova matriz, você pode usar sample:

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

Você pode classificar sua matriz com chave aleatória

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

a chave seja lida apenas uma vez, para comparar o item durante a classificação ainda eficiente.

mas parece que random.shuffle(array)será mais rápido, uma vez que está escrito em C

Trinh Hoang Nhu
fonte
1
isso cria um novo elemento aleatório para cada elemento da matriz?
Javadba # 14/18
@javadba Não, apenas uma espécie um array pelo índice aleatório que vai acabar embaralhar a matriz
Trinh Hoang Nhu
1
Desculpe eu talvez não estava claro que eu não queria dizer o arrayque eu quis dizer o Randomelemento: ou seja, no lambdao random.random()novo pode estar gerando Randominstância de classe de cada vez. Na verdade, não tenho certeza: javaseria a maneira errada de fazer isso: você deve criar um Random rng = Random()e depois chamar o rng.nextGaussian(). Mas não sabe como python random.random()funciona
javadba
1
Embora seu código possa ser corrigido como resposta, mas elaborando o que seu código faz, ele pode melhorar a qualidade de sua resposta. Confira o artigo: Como faço para escrever uma boa resposta?
21718 Luffy #
1

Além das respostas anteriores, gostaria de introduzir outra função.

numpy.random.shufflebem como random.shuffleexecutar baralhamento no local. No entanto, se você deseja retornar uma matriz aleatória, numpy.random.permutationé a função a ser usada.

Sabre
fonte
1

Eu não sei o que usei, random.shuffle()mas ele retornou 'Nenhum' para mim, então escrevi isso, pode ser útil para alguém

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
fonte
2
sim, ele retorna None, mas o array é modificado, se você realmente deseja retornar algo, faça esta importação aleatória 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
fonte
0

Esteja ciente de que random.shuffle()não deve ser usado em matrizes multidimensionais, pois causa repetições.

Imagine que você deseja embaralhar uma matriz ao longo de sua primeira dimensão, podemos criar o seguinte exemplo de teste,

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, ao longo do primeiro eixo, o i-ésimo elemento corresponda a uma matriz 2x3 em que todos os elementos são iguais a i.

Se usarmos a função aleatória correta para matrizes multidimensionais, ou seja np.random.shuffle(x), a matriz será embaralhada ao longo do primeiro eixo, conforme desejado. No entanto, o uso random.shuffle(x)causará repetições. Você pode verificar isso executando o len(np.unique(x))shuffling, o que fornece 10 (conforme o esperado), np.random.shuffle()mas apenas cerca de 5 ao usar random.shuffle().

Wise Cloud
fonte