menghapus baris dalam larik numpy

90

Saya memiliki array yang mungkin terlihat seperti ini:

ANOVAInputMatrixValuesArray = [[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 
0.53172222], [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]]

Perhatikan bahwa salah satu baris memiliki nilai nol di bagian akhir. Saya ingin menghapus baris apa pun yang berisi nol, sambil mempertahankan baris apa pun yang berisi nilai bukan nol di semua sel.

Tetapi array akan memiliki jumlah baris yang berbeda setiap kali diisi, dan angka nol akan ditempatkan di baris yang berbeda setiap saat.

Saya mendapatkan jumlah elemen bukan nol di setiap baris dengan baris kode berikut:

NumNonzeroElementsInRows    = (ANOVAInputMatrixValuesArray != 0).sum(1)

Untuk larik di atas, NumNonzeroElementsInRows berisi: [5 4]

Lima menunjukkan bahwa semua nilai yang mungkin di baris 0 adalah bukan nol, sedangkan empat menunjukkan bahwa salah satu nilai yang mungkin di baris 1 adalah nol.

Oleh karena itu, saya mencoba menggunakan baris kode berikut untuk menemukan dan menghapus baris yang berisi nilai nol.

for q in range(len(NumNonzeroElementsInRows)):
    if NumNonzeroElementsInRows[q] < NumNonzeroElementsInRows.max():
        p.delete(ANOVAInputMatrixValuesArray, q, axis=0)

Tetapi untuk beberapa alasan, kode ini tampaknya tidak melakukan apa-apa, meskipun melakukan banyak perintah cetak menunjukkan bahwa semua variabel tampaknya terisi dengan benar mengarah ke kode.

Pasti ada cara mudah untuk hanya "menghapus baris apa pun yang berisi nilai nol".

Adakah yang bisa menunjukkan kepada saya kode apa yang harus ditulis untuk mencapai ini?

MedicalMath
sumber

Jawaban:

166

Cara termudah untuk menghapus baris dan kolom dari array adalah dengan numpy.deletemetode.

Misalkan saya memiliki array berikut x:

x = array([[1,2,3],
        [4,5,6],
        [7,8,9]])

Untuk menghapus baris pertama, lakukan ini:

x = numpy.delete(x, (0), axis=0)

Untuk menghapus kolom ketiga, lakukan ini:

x = numpy.delete(x,(2), axis=1)

Jadi Anda bisa menemukan indeks dari baris yang memiliki 0 di dalamnya, meletakkannya dalam daftar atau tupel dan meneruskan ini sebagai argumen kedua dari fungsi tersebut.

Jaidev Deshpande
sumber
Terima kasih! Saya memiliki masalah yang sama, dan saya tidak tahu mengapa menelepon numpy.delete(x, index)saja tidak berhasil.
Antimony
6
perhatikan bahwa dokumen numpy delete () menunjukkan bahwa "Seringkali lebih baik menggunakan boolean mask" karena array baru dikembalikan - contoh disediakan di bawah tautan itu
arturomp
1
@arturomp tetapi topengnya tidak merusak. Apakah panggilan untuk menghapus () memakan waktu / memori?
Nathan
14

Ini satu liner (ya, ini mirip dengan user333700, tetapi sedikit lebih mudah):

>>> import numpy as np
>>> arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222], 
                [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]])
>>> print arr[arr.all(1)]
array([[ 0.96488889,  0.73641667,  0.67521429,  0.592875  ,  0.53172222]])

Omong-omong, metode ini jauh lebih cepat daripada metode array bertopeng untuk matriks besar. Untuk matriks 2048 x 5, metode ini sekitar 1000x lebih cepat.

Ngomong-ngomong, metode user333700 (dari komentarnya) sedikit lebih cepat dalam pengujian saya, meskipun itu mengejutkan saya mengapa.

Justin Peel
sumber
3
"any" dapat mengalami korsleting, segera setelah kasus benar pertama terdeteksi, ia dapat berhenti, sementara "semua" harus memeriksa semua kondisi. Jadi, tidak ("~" di numpy) apapun, secara umum harus lebih cepat dari semuanya.
Josef
4
@ user333700, keduanya dapat mengalami korsleting, hanya untuk hal yang berbeda. anyarus pendek ke true pada kasus benar pertama yang terdeteksi; allarus pendek ke false pada kasus salah pertama yang terdeteksi. Dalam hal ini, korsleting harusnya seri, tetapi melakukan ekstra tidak akan membuatnya lebih lambat menurut saya.
Justin Peel
5

Ini mirip dengan pendekatan awal Anda, dan akan menggunakan lebih sedikit ruang daripada jawaban unutbu , tapi saya rasa ini akan lebih lambat.

>>> import numpy as np
>>> p = np.array([[1.5, 0], [1.4,1.5], [1.6, 0], [1.7, 1.8]])
>>> p
array([[ 1.5,  0. ],
       [ 1.4,  1.5],
       [ 1.6,  0. ],
       [ 1.7,  1.8]])
>>> nz = (p == 0).sum(1)
>>> q = p[nz == 0, :]
>>> q
array([[ 1.4,  1.5],
       [ 1.7,  1.8]])

Ngomong-ngomong, baris p.delete()Anda tidak berfungsi untuk saya - ndarraykarena tidak memiliki .deleteatribut.

mtrw
sumber
8
sedikit lebih sederhana: p [~ (p == 0) .any (1)] atau lebih eksplisit untuk baris: p [~ (p == 0) .any (1),:]
Josef
2

numpy menyediakan fungsi sederhana untuk melakukan hal yang persis sama: misalkan Anda memiliki array bertopeng 'a', memanggil numpy.ma.compress_rows (a) akan menghapus baris yang berisi nilai bertopeng. Saya kira ini jauh lebih cepat seperti ini ...

jep
sumber
1
import numpy as np 
arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222],[ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]])
print(arr[np.where(arr != 0.)])
Prokhozhii
sumber
-1

Saya mungkin akan terlambat menjawab pertanyaan ini, namun ingin berbagi masukan untuk kepentingan masyarakat. Untuk contoh ini, izinkan saya memanggil matriks Anda 'ANOVA', dan saya mengasumsikan Anda hanya mencoba menghapus baris dari matriks ini dengan 0 hanya di kolom ke-5.

indx = []
for i in range(len(ANOVA)):
    if int(ANOVA[i,4]) == int(0):
        indx.append(i)

ANOVA = [x for x in ANOVA if not x in indx]
troymyname00.dll
sumber