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
Себерг
1
До numy 1.7 используйте random .sample (xrange (10), 2)
Денис
3
почему вы называете свои переменные A и B и все такое? это затрудняет чтение.
Буратино
48

Это старый пост, но это то, что лучше всего работает для меня:

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

измените replace = False на True, чтобы получить то же самое, но с заменой.

Хези Решефф
источник
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% строк, выбранных случайным образом.

isosceleswheel
источник
Вы можете добавить, replace = Falseесли вы не хотите проб с заменой.
Сара
@Sarah Замена не является проблемой с этим методом выборки, потому что значение True / False возвращается для каждой позиции в data_arr . В моем примере будет случайным ~ 25% позиций, Trueи эти позиции будут выбраны data_arr.
равнобедренное колесо
10

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

Вы можете получить несколько случайных индексов из вашего массива, используя:

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

Затем вы можете использовать нарезку с вашим массивом numpy, чтобы получить образцы по этим индексам:

A[indices]

Это даст вам указанное количество случайных выборок из ваших данных.

CB Madsen
источник
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)

Здесь x, должно быть «int», определяющим количество строк, которые вы хотите выбрать случайным образом.

Анкит Агравал
источник
4
Это работает, только если old_arrayэто последовательность или набор, а не пустой массив [ссылка] ( docs.python.org/3/library/random.html#functions-for-sequence )
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, :]
Бен
источник