Numpy: obtenha um conjunto aleatório de linhas da matriz 2D

159

Eu tenho uma matriz 2D muito grande que se parece com isso:

a=
[[a1, b1, c1],
 [a2, b2, c2],
 ...,
 [an, bn, cn]]

Usando numpy, existe uma maneira fácil de obter uma nova matriz 2D com, por exemplo, 2 linhas aleatórias da matriz inicial a (sem substituição)?

por exemplo

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]
gha
fonte
8
é tolice ter uma pergunta para substituição e outra sem, você deve apenas permitir as duas respostas e, de fato, incentivar as duas respostas.
Pinóquio

Respostas:

193
>>> A = np.random.randint(5, size=(10,3))
>>> A
array([[1, 3, 0],
       [3, 2, 0],
       [0, 2, 1],
       [1, 1, 4],
       [3, 2, 2],
       [0, 1, 0],
       [1, 3, 1],
       [0, 4, 1],
       [2, 4, 2],
       [3, 3, 1]])
>>> idx = np.random.randint(10, size=2)
>>> idx
array([7, 6])
>>> A[idx,:]
array([[0, 4, 1],
       [1, 3, 1]])

Juntando-o para um caso geral:

A[np.random.randint(A.shape[0], size=2), :]

Para não substituição (numpy 1.7.0+):

A[np.random.choice(A.shape[0], 2, replace=False), :]

Não acredito que haja uma boa maneira de gerar lista aleatória sem substituição antes da 1.7. Talvez você possa configurar uma definição pequena que garanta que os dois valores não sejam os mesmos.

Daniel
fonte
4
Talvez não exista uma boa maneira, mas uma maneira que seja tão boa quanto np.random.choice, e que seja np.random.permutation(A.shape[0])[:2], na verdade não seja ótima, mas é o que np.random.choiceneste momento ... ou se você não quiser alterar sua matriz. local,np.random.shuffle
seberg
1
Antes do numpy 1.7, use .sample aleatório (xrange (10), 2)
denis
3
por que você está nomeando suas variáveis ​​A e B e outras coisas? dificulta a leitura.
Pinóquio
48

Este é um post antigo, mas é o que funciona melhor para mim:

A[np.random.choice(A.shape[0], num_rows_2_sample, replace=False)]

altere o replace = False para True para obter a mesma coisa, mas com a substituição.

Hezi Resheff
fonte
2
@SalvadorDali Eu editei a publicação de Hezi para não escolher com substituição. Depois que a edição for revisada por pares, você verá o replace=Falseparâmetro adicionado a choice.
0243209r9 17/10/19
8
@ 0x24a537r9 você não deve fazer isso. Esta é a resposta dele e você a altera. Se você quiser - adicione sua resposta um não mudam respostas de outras pessoas que altera significativamente a resposta
Salvador Dali
@SalvadorDali por que não?
Scott
25

Outra opção é criar uma máscara aleatória se você quiser apenas fazer uma amostragem reduzida de seus dados por um determinado fator. Digamos que eu queira fazer uma amostragem reduzida para 25% do meu conjunto de dados original, atualmente mantido na matriz data_arr:

# generate random boolean mask the length of data
# use p 0.75 for False and 0.25 for True
mask = numpy.random.choice([False, True], len(data_arr), p=[0.75, 0.25])

Agora você pode chamar data_arr[mask]e retornar ~ 25% das linhas, amostradas aleatoriamente.

isosceleswheel
fonte
10

Essa é uma resposta semelhante à fornecida por Hezi Rasheff, mas simplificada para que novos usuários de python entendam o que está acontecendo (notei que muitos novos estudantes de ciência de dados obtêm amostras aleatórias das maneiras mais estranhas, porque não sabem o que estão fazendo em python).

Você pode obter vários índices aleatórios da sua matriz usando:

indices = np.random.choice(A.shape[0], amount_of_samples, replace=False)

Você pode usar o fatiamento com sua matriz numpy para obter as amostras nesses índices:

A[indices]

Isso fornecerá o número especificado de amostras aleatórias dos seus dados.

CB Madsen
fonte
5

Se você precisar das mesmas linhas, mas apenas uma amostra aleatória,

import random
new_array = random.sample(old_array,x)

Aqui x, deve ser um 'int' definindo o número de linhas que você deseja escolher aleatoriamente.

Ankit Agrawal
fonte
3
Isto só funciona se old_arrayé uma sequência ou um conjunto, não uma matriz numpy [Link] ( docs.python.org/3/library/random.html#functions-for-sequences )
leermeester
5

Vejo que a permutação foi sugerida. De fato, ele pode ser transformado em uma linha:

>>> A = np.random.randint(5, size=(10,3))
>>> np.random.permutation(A)[:2]

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

Se você deseja gerar vários subconjuntos aleatórios de linhas, por exemplo, se você estiver executando o RANSAC.

num_pop = 10
num_samples = 2
pop_in_sample = 3
rows_to_sample = np.random.random([num_pop, 5])
random_numbers = np.random.random([num_samples, num_pop])
samples = np.argsort(random_numbers, axis=1)[:, :pop_in_sample]
# will be shape [num_samples, pop_in_sample, 5]
row_subsets = rows_to_sample[samples, :]
Ben
fonte