Saya berjuang untuk memilih kolom spesifik per baris dari sebuah NumPy
matriks.
Misalkan saya memiliki matriks berikut yang akan saya sebut X
:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Saya juga memiliki list
indeks kolom per setiap baris yang akan saya sebut Y
:
[1, 0, 2]
Saya perlu mendapatkan nilainya:
[2]
[4]
[9]
Alih-alih a list
dengan indeks Y
, saya juga dapat menghasilkan matriks dengan bentuk yang sama seperti di X
mana setiap kolom adalah a bool
/ int
dalam rentang nilai 0-1, yang menunjukkan apakah ini kolom yang diperlukan.
[0, 1, 0]
[1, 0, 0]
[0, 0, 1]
Saya tahu ini dapat dilakukan dengan iterasi pada array dan memilih nilai kolom yang saya butuhkan. Namun, ini akan sering dieksekusi pada array data yang besar dan itulah mengapa harus dijalankan secepat mungkin.
Saya jadi bertanya-tanya apakah ada solusi yang lebih baik?
Terima kasih.
sumber
Jawaban:
Jika Anda memiliki array boolean, Anda dapat melakukan seleksi langsung berdasarkan itu seperti:
>>> a = np.array([True, True, True, False, False]) >>> b = np.array([1,2,3,4,5]) >>> b[a] array([1, 2, 3])
Untuk mengikuti contoh awal Anda, Anda dapat melakukan hal berikut:
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> b = np.array([[False,True,False],[True,False,False],[False,False,True]]) >>> a[b] array([2, 4, 9])
Anda juga dapat menambahkan
arange
dan melakukan seleksi langsung, meskipun tergantung pada bagaimana Anda membuat array boolean dan seperti apa kode Anda YMMV.>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> a[np.arange(len(a)), [1,0,2]] array([2, 4, 9])
Semoga dapat membantu, beri tahu saya jika Anda memiliki pertanyaan lain.
sumber
arange
. Ini sangat berguna bagi saya untuk mengambil blok yang berbeda dari beberapa matriks (jadi pada dasarnya kasus 3D dari contoh ini)arange
bukan:
? Saya tahu cara Anda berhasil dan cara saya tidak, tetapi saya ingin memahami alasannya.:
sintaksnya tidak berfungsi dengan cara yang sama.:
dengan pengindeksan lanjutan berarti: "untuk setiap sub-ruang bersama:
, terapkan pengindeksan lanjutan yang diberikan". Apakah pemahaman saya benar?Anda bisa melakukan sesuatu seperti ini:
In [7]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [8]: lst = [1, 0, 2] In [9]: a[np.arange(len(a)), lst] Out[9]: array([2, 4, 9])
Selengkapnya tentang pengindeksan array multi-dimensi: http://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays
sumber
:
akan menampilkan hasil beberapalen(a)
kali, sebaliknya, menunjukkan indeks setiap baris akan mencetak hasil yang diantisipasi.Cara sederhana mungkin terlihat seperti:
In [1]: a = np.array([[1, 2, 3], ...: [4, 5, 6], ...: [7, 8, 9]]) In [2]: y = [1, 0, 2] #list of indices we want to select from matrix 'a'
range(a.shape[0])
akan kembaliarray([0, 1, 2])
In [3]: a[range(a.shape[0]), y] #we're selecting y indices from every row Out[3]: array([2, 4, 9])
sumber
numpy
Versi terbaru telah menambahkantake_along_axis
(danput_along_axis
) yang melakukan pengindeksan ini dengan bersih.In [101]: a = np.arange(1,10).reshape(3,3) In [102]: b = np.array([1,0,2]) In [103]: np.take_along_axis(a, b[:,None], axis=1) Out[103]: array([[2], [4], [9]])
Ini beroperasi dengan cara yang sama seperti:
In [104]: a[np.arange(3), b] Out[104]: array([2, 4, 9])
tetapi dengan penanganan sumbu yang berbeda. Ini secara khusus ditujukan untuk menerapkan hasil dari
argsort
danargmax
.sumber
Anda dapat melakukannya dengan menggunakan iterator. Seperti ini:
np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int)
Waktu:
N = 1000 X = np.zeros(shape=(N, N)) Y = np.arange(N) #@Aशwini चhaudhary %timeit X[np.arange(len(X)), Y] 10000 loops, best of 3: 30.7 us per loop #mine %timeit np.fromiter((row[index] for row, index in zip(X, Y)), dtype=int) 1000 loops, best of 3: 1.15 ms per loop #mine %timeit np.diag(X.T[Y]) 10 loops, best of 3: 20.8 ms per loop
sumber
np.diag(X.T[Y])
sangat lambat ... Tapinp.diag(X.T)
sangat cepat (10us). Saya tidak tahu kenapa.Cara cerdas lainnya adalah dengan terlebih dahulu mengubah urutan array dan mengindeksnya setelahnya. Akhirnya, ambil diagonal, selalu jawaban yang benar.
X = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) Y = np.array([1, 0, 2, 2]) np.diag(X.T[Y])
Selangkah demi selangkah:
Array asli:
>>> X array([[ 1, 2, 3], [ 4, 5, 6], [ 7, 8, 9], [10, 11, 12]]) >>> Y array([1, 0, 2, 2])
Ubah urutan agar memungkinkan untuk mengindeksnya dengan benar.
>>> X.T array([[ 1, 4, 7, 10], [ 2, 5, 8, 11], [ 3, 6, 9, 12]])
Dapatkan baris dalam urutan Y.
>>> X.T[Y] array([[ 2, 5, 8, 11], [ 1, 4, 7, 10], [ 3, 6, 9, 12], [ 3, 6, 9, 12]])
Diagonal sekarang akan menjadi jelas.
>>> np.diag(X.T[Y]) array([ 2, 4, 9, 12]
sumber