Numpy: Dapatkan set acak baris dari array 2D

160

Saya memiliki array 2D yang sangat besar yang terlihat seperti ini:

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

Menggunakan numpy, apakah ada cara mudah untuk mendapatkan array 2D baru dengan, misalnya, 2 baris acak dari array awal a(tanpa penggantian)?

misalnya

b=
[[a4,  b4,  c4],
 [a99, b99, c99]]
gha
sumber
8
konyol untuk memiliki satu pertanyaan untuk penggantian dan satu tanpa, Anda harus membiarkan kedua jawaban dan bahkan mendorong kedua jawaban.
Pinocchio

Jawaban:

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

Menyatukannya untuk kasus umum:

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

Untuk yang bukan pengganti (numpy 1.7.0+):

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

Saya tidak percaya ada cara yang baik untuk menghasilkan daftar acak tanpa penggantian sebelum 1,7. Mungkin Anda dapat mengatur definisi kecil yang memastikan kedua nilai tidak sama.

Daniel
sumber
4
Mungkin tidak ada cara yang baik, tetapi cara yang sama baiknya np.random.choice, dan itu np.random.permutation(A.shape[0])[:2], sebenarnya tidak bagus, tapi itulah yang np.random.choicesaat ini ... atau jika Anda tidak peduli untuk mengubah array Anda di- tempat,np.random.shuffle
seberg
1
Sebelum numpy 1.7, gunakan .sample acak (xrange (10), 2)
denis
3
mengapa Anda memberi nama variabel A dan B dan yang lainnya? itu membuatnya lebih sulit untuk dibaca.
Pinocchio
48

Ini adalah pos lama, tetapi inilah yang paling cocok untuk saya:

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

ganti ganti = Salah ke Benar untuk mendapatkan hal yang sama, tetapi dengan penggantian.

Hezi Resheff
sumber
2
@SalvadorDali Saya sudah mengedit posting Hezi untuk tidak memilih dengan pengganti. Setelah hasil edit ditinjau sejawat, Anda akan melihat replace=Falseparam yang ditambahkan ke choice.
0x24a537r9
8
@ 0x24a537r9 Anda seharusnya tidak melakukan ini. Ini adalah jawabannya dan Anda mengubahnya. Jika Anda mau - tambahkan jawaban Anda dan jangan ubah jawaban orang lain yang secara signifikan mengubah jawaban
Salvador Dali
@SalvadorDali kenapa tidak?
Scott
25

Pilihan lain adalah membuat topeng acak jika Anda hanya ingin mengambil sampel data Anda dengan faktor tertentu. Katakanlah saya ingin mengambil sampel hingga 25% dari kumpulan data asli saya, yang saat ini disimpan dalam array 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])

Sekarang Anda dapat menelepon data_arr[mask]dan mengembalikan ~ 25% dari baris, yang diambil secara acak.

roda sama kaki
sumber
Anda mungkin ingin menambahkan replace = Falsejika Anda tidak ingin pengambilan sampel dengan penggantian.
Sarah
@Sarah Replacement bukan masalah dengan metode pengambilan sampel ini karena nilai Benar / Salah dikembalikan untuk setiap posisi di data_arr. Dalam contoh saya, acak ~ 25% dari posisi akan Truedan posisi tersebut diambil dari sampel data_arr.
isosceleswheel
10

Ini adalah jawaban yang mirip dengan yang Hezi Rasheff berikan, tetapi disederhanakan sehingga pengguna python yang lebih baru memahami apa yang terjadi (saya melihat banyak siswa ilmu data baru mengambil sampel acak dengan cara yang paling aneh karena mereka tidak tahu apa yang mereka lakukan dengan python).

Anda bisa mendapatkan sejumlah indeks acak dari array Anda dengan menggunakan:

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

Anda kemudian dapat menggunakan slicing dengan array numpy Anda untuk mendapatkan sampel di indeks tersebut:

A[indices]

Ini akan memberi Anda jumlah sampel acak yang ditentukan dari data Anda.

CB Madsen
sumber
5

Saya melihat permutasi telah disarankan. Bahkan dapat dibuat menjadi satu baris:

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

array([[0, 3, 0],
       [3, 1, 2]])
orli
sumber
4

Jika Anda membutuhkan baris yang sama tetapi hanya sampel acak,

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

Di sini x, harus menjadi 'int' yang mendefinisikan jumlah baris yang ingin Anda pilih secara acak.

Ankit Agrawal
sumber
4
Ini hanya berfungsi jika old_arraymerupakan urutan atau set, bukan array numpy [tautan] ( docs.python.org/3/library/random.html#functions-for- followingences )
leermeester
2

Jika Anda ingin membuat beberapa himpunan bagian acak dari baris, misalnya jika Anda melakukan 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
sumber