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]]

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.


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.


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.


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.



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]])

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, :]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.