Numpy: Отримайте випадковий набір рядків з 2D масиву


160

У мене дуже великий 2D масив, який виглядає приблизно так:

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

Використовуючи numpy, чи є простий спосіб отримати новий 2D масив, наприклад, з 2 випадкових рядків з початкового масиву a(без заміни)?

напр

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]

8
нерозумно мати питання для заміни, а одне без, ви просто повинні дозволити обидві відповіді і насправді заохотити обидва відповіді.
Буратіно

Відповіді:


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

Збираючи це разом для загального випадку:

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

Для не заміни (numpy 1.7.0+):

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

Я не вірю, що існує хороший спосіб генерувати випадковий список без заміни до 1,7. Можливо, ви можете встановити невелике визначення, яке забезпечує два значення не однакові.


4
Можливо, це не хороший шлях, але такий самий хороший спосіб np.random.choice, і це np.random.permutation(A.shape[0])[:2], власне, його не дуже добре, але це те, що np.random.choiceв цей час ... або якщо вам не байдуже змінити масив в місце,np.random.shuffle
seberg

1
Перед numpy 1.7 використовуйте випадковий .sample (xrange (10), 2)
denis

3
чому ти називаєш свої змінні A і B та інше? це ускладнює читання.
Буратіно

48

Це стара публікація, але це найкраще для мене:

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

змінити заміну = Неправильне на Істинне, щоб отримати те саме, але з заміною.


2
@SalvadorDali Я редагував пост Хезі, щоб не вибирати його заміною. Після рецензування редагування ви побачите доданий replace=Falseпараметр до choice.
0x24a537r9

8
@ 0x24a537r9 ви не повинні цього робити. Це його відповідь, і ви її міняєте. Якщо ви хочете - додайте свою відповідь, не змінюйте відповіді інших людей, що суттєво змінює відповідь
Сальвадор Далі

@SalvadorDali чому б і ні?
Скотт

25

Інший варіант - створити випадкову маску, якщо ви просто хочете зменшити вибірку даних за певним фактором. Скажіть, я хочу зменшити вибірку до 25% мого початкового набору даних, який зараз знаходиться в масиві 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])

Тепер ви можете зателефонувати data_arr[mask]та повернутись ~ 25% рядків, випадково відібраних у вибірку.


Ви можете додати, replace = Falseякщо ви не хочете вибірки з заміною.
Сара

10

Це аналогічна відповідь на ту, яку надав Хезі Рашефф, але спрощений, тому нові користувачі пітонів розуміють, що відбувається (я помітив, що багато нових студентів-науковців отримують випадкові вибірки найсмішнішими способами, оскільки вони не знають, що роблять у пітоні).

Ви можете отримати ряд випадкових індексів зі свого масиву, використовуючи:

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

Потім ви можете використовувати нарізку з масивом numpy, щоб отримати зразки за цими показниками:

A[indices]

Це дозволить отримати вказану кількість випадкових зразків із ваших даних.


5

Я бачу перестановку запропоновано. Насправді його можна скласти в один рядок:

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

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

4

Якщо вам потрібні ті самі рядки, але лише випадковий зразок,

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

Тут х має бути "int", що визначає кількість рядків, які ви хочете випадковим чином вибрати.


4
Це працює лише в тому випадку, якщо old_arrayце послідовність або набір, а не масивний масив [посилання] ( docs.python.org/3/library/random.html#functions-for-sequences )
leermeester

2

Якщо ви хочете генерувати кілька випадкових підмножин рядків, наприклад, якщо ви робите 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, :]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.