Katakanlah saya memiliki array Numpy a dengan bentuk (10, 10, 4, 5, 3, 3), dan dua daftar indeks, b dan c, dengan bentuk (1000, 6) dan (1000, 5) masing-masing, yang mewakili indeks dan indeks parsial untuk array. Saya ingin menggunakan indeks untuk mengakses array, menghasilkan array bentuk (1000,) dan (1000, 3), masing-masing.

Saya tahu beberapa cara untuk melakukan ini, tetapi semuanya berat dan agak tidak pythonik, misalnya mengonversi indeks menjadi tupel atau mengindeks setiap sumbu secara terpisah.

a = np.random.random((10, 10, 4, 5, 3, 3))
b = np.random.randint(3, size=(1000, 6))
c = np.random.randint(3, size=(1000, 5))

# method one

tuple_index_b = [tuple(row) for row in b]
tuple_index_c = [tuple(row) for row in c]

output_b = np.array([a[row] for row in tuple_index_b])
output_c = np.array([a[row] for row in tuple_index_c])

# method two

output_b = a[b[:, 0], b[:, 1], b[:, 2], b[:, 3], b[:, 4], b[:, 5]]
output_c = a[c[:, 0], c[:, 1], c[:, 2], c[:, 3], c[:, 4]]

Jelas, tidak satu pun dari metode ini yang sangat elegan atau sangat mudah diperluas ke dimensi yang lebih tinggi. Yang pertama juga sangat lambat, dengan dua pemahaman daftar, dan yang kedua mengharuskan Anda untuk menulis setiap sumbu secara terpisah. Sintaks intuitif, a[b] mengembalikan larik bentuk (1000, 6, 10, 4, 5, 3, 3) untuk beberapa alasan, kemungkinan terkait dengan penyiaran.

Jadi, apakah ada cara untuk melakukan ini di Numpy yang tidak melibatkan banyak tenaga/waktu manual?

Sunting: Tidak benar-benar duplikat, karena pertanyaan ini berkaitan dengan daftar indeks multidimensi, dan bukan hanya indeks tunggal, dan telah menghasilkan beberapa metode baru yang berguna.

3
JAustin 14 Agustus 2017, 18:56

2 jawaban

Jawaban Terbaik

Anda dapat mengonversi indeks menjadi tuple di mana setiap kolom adalah elemen terpisah dan kemudian menggunakan __getitem__, dengan asumsi indeks selalu merupakan beberapa dimensi pertama:

a.__getitem__(tuple(b.T))

Atau sederhananya:

a[tuple(b.T)]

(a.__getitem__(tuple(b.T)) == output_b).all()
# True

(a.__getitem__(tuple(c.T)) == output_c).all()
# True

(a[tuple(b.T)] == output_b).all()
# True

(a[tuple(c.T)] == output_c).all()
# True
3
Psidom 14 Agustus 2017, 16:06

Metode tiga:

output_b = a[map(np.ravel, b.T)]
output_c = a[map(np.ravel, c.T)]
1
AGN Gazer 14 Agustus 2017, 16:06