Numpy: Uzyskaj losowy zestaw wierszy z tablicy 2D

160

Mam bardzo dużą tablicę 2D, która wygląda mniej więcej tak:

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

Używając numpy, czy istnieje łatwy sposób na uzyskanie nowej tablicy 2D z np. 2 losowymi wierszami z początkowej tablicy a(bez zamiany)?

na przykład

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]
gha
źródło
8
głupio jest mieć pytanie jedno do zastąpienia, a drugie bez, powinieneś po prostu pozwolić na obie odpowiedzi i faktycznie zachęcać do obu odpowiedzi.
Pinokio

Odpowiedzi:

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

Składając to razem dla ogólnego przypadku:

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

W przypadku produktów niewymiennych (numpy 1.7.0+):

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

Nie wierzę, że istnieje dobry sposób na wygenerowanie losowej listy bez wymiany przed 1.7. Być może możesz ustawić małą definicję, która zapewni, że te dwie wartości nie będą takie same.

Daniel
źródło
4
Może nie ma dobrego sposobu, ale sposób, który jest tak dobry, jak np.random.choice, i to np.random.permutation(A.shape[0])[:2]właściwie nie jest świetny, ale to jest to, co np.random.choicew tej chwili ... lub jeśli nie chcesz zmieniać swojej tablicy w- miejsce,np.random.shuffle
seberg
1
Przed numpy 1.7 użyj random .sample (xrange (10), 2)
denis
3
dlaczego nazywasz swoje zmienne A i B i tak dalej? utrudnia czytanie.
Pinokio
48

To jest stary post, ale to działa najlepiej dla mnie:

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

zmień replace = False na True, aby uzyskać to samo, ale z wymianą.

Hezi Resheff
źródło
2
@SalvadorDali Zredagowałem post Hezi, aby nie wybierać z wymianą. Gdy zmiana zostanie zweryfikowana, zobaczysz dodany replace=Falseparametr do choice.
0x24a537r9
8
@ 0x24a537r9 nie powinieneś tego robić. To jest jego odpowiedź i ty ją zmieniasz. Jeśli chcesz - dodaj swoją odpowiedź i nie zmieniaj odpowiedzi innych osób, co znacząco zmienia odpowiedź
Salvador Dali
@SalvadorDali, czemu nie?
Scott
25

Inną opcją jest utworzenie losowej maski, jeśli chcesz po prostu zmniejszyć próbkowanie danych o określony czynnik. Powiedzmy, że chcę pobrać próbkowanie do 25% mojego pierwotnego zestawu danych, który jest obecnie przechowywany w tablicy 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])

Teraz możesz wywoływać data_arr[mask]i zwracać ~ 25% wierszy, losowo próbkowanych.

koło równoramienne
źródło
Możesz dodać, replace = Falsejeśli nie chcesz próbkowania z wymianą.
Sarah
10

Jest to odpowiedź podobna do tej, którą dostarczył Hezi Rasheff, ale jest uproszczona, dzięki czemu nowi użytkownicy Pythona rozumieją, co się dzieje (zauważyłem, że wielu nowych studentów nauki danych pobiera losowe próbki w najdziwniejszy sposób, ponieważ nie wiedzą, co robią w Pythonie).

Możesz uzyskać wiele losowych indeksów ze swojej tablicy, używając:

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

Następnie możesz użyć wycinania z tablicą numpy, aby pobrać próbki w tych indeksach:

A[indices]

Dzięki temu uzyskasz określoną liczbę losowych próbek z Twoich danych.

CB Madsen
źródło
5

Widzę, że zaproponowano permutację. W rzeczywistości można to zrobić w jednej linii:

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

array([[0, 3, 0],
       [3, 1, 2]])
orli
źródło
4

Jeśli potrzebujesz tych samych wierszy, ale tylko losowej próbki,

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

Tutaj x musi być liczbą „int” określającą liczbę wierszy, które chcesz losowo wybrać.

Ankit Agrawal
źródło
4
Działa to tylko wtedy, gdy old_arrayjest sekwencją lub zestawem, a nie tablicą numpy [link] ( docs.python.org/3/library/random.html#functions-for-sequences )
leermeester
2

Jeśli chcesz wygenerować wiele losowych podzbiorów wierszy, na przykład jeśli wykonujesz 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
źródło