Cara menghapus elemen tertentu dalam array numpy

212

Bagaimana saya bisa menghapus beberapa elemen spesifik dari array yang numpy? Katakan saya punya

import numpy as np

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

Saya kemudian ingin menghapus 3,4,7dari a. Yang saya tahu adalah indeks nilai ( index=[2,3,6]).

Daniel Thaagaard Andreasen
sumber

Jawaban:

286

Gunakan numpy.delete () - mengembalikan array baru dengan sub-array sepanjang sumbu dihapus

numpy.delete(a, index)

Untuk pertanyaan spesifik Anda:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = [2, 3, 6]

new_a = np.delete(a, index)

print(new_a) #Prints `[1, 2, 5, 6, 8, 9]`

Perhatikan bahwa numpy.delete()mengembalikan array baru karena skalar array tidak dapat diubah, mirip dengan string dalam Python, jadi setiap kali perubahan dibuat untuk itu, objek baru dibuat. Yaitu, mengutip delete() dokumen :

" Salinan arr dengan elemen yang ditentukan oleh obj dihapus. Perhatikan bahwa penghapusan tidak terjadi di tempat ..."

Jika kode yang saya posting memiliki output, itu adalah hasil menjalankan kode.

Levon
sumber
1
@IngviGautsson Ketika Anda mengedit, Anda juga mengubah nilai yang benar untuk elemen dari 2, 3, 6 ke 3, 4, 7, jika Anda menjalankan kode sekarang Anda tidak mendapatkan output yang benar seperti pada kasus aslinya. "Saya memutar kembali hasil edit
Levon
1
AttributeError: objek 'list' tidak memiliki atribut 'delete'
munmunbb
3
@IngviGautsson Tidak, komentar Anda menyesatkan. Ini berfungsi seperti yang diharapkan. Namun, dokumentasi numpy.delete () tidak mencatat bahwa "sering lebih baik menggunakan topeng boolean"; contoh itu juga diberikan.
Biggsy
1
@Levon dapatkah Anda menambahkan contoh untuk 2D?
MattS
7
@IngviGautsson Anda salah. Dibutuhkan indeks item untuk dihapus, bukan item itu sendiri.
Le Frite
64

Ada fungsi built-in numpy untuk membantu dengan itu.

import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.array([3,4,7])
>>> c = np.setdiff1d(a,b)
>>> c
array([1, 2, 5, 6, 8, 9])
Zong
sumber
7
Senang mendengarnya. Saya berpikir bahwa np.delete akan lebih lambat tapi sayangnya, timeit untuk 1000 integer mengatakan delete adalah x2 lebih cepat.
wbg
1
Ini bagus karena beroperasi pada nilai- nilai array daripada harus memberikan indeks / indeks yang ingin Anda hapus. Misalnya:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004
Ini juga memilah output, yang mungkin bukan yang diinginkan. Kalau tidak, sangat bagus.
rayzinnz
Pertanyaannya mengatakan "Yang saya tahu adalah indeks nilai". Jadi, ini tentang menghapus item dengan indeks mereka , tidak menghapus dengan nilai-nilai mereka
Sherzod
35

Array Numpy tidak dapat diubah , artinya Anda secara teknis tidak dapat menghapus item darinya. Namun, Anda dapat membuat array baru tanpa nilai yang tidak Anda inginkan, seperti ini:

b = np.delete(a, [2,3,6])
Digitalex
sumber
1
+1 untuk menyebutkan 'tidak berubah'. Adalah baik untuk diingat, bahwa array numpy tidak baik untuk perubahan ukuran yang cepat (menambahkan / menghapus elemen)
eumiro
38
Secara teknis, array numpy dapat berubah. Misalnya, ini: a[0]=1memodifikasi adi tempat. Tapi mereka tidak bisa diubah ukurannya.
btel
3
Definisi mengatakan itu tidak berubah, tetapi jika dengan menetapkan nilai baru itu membiarkan Anda memodifikasi, lalu bagaimana itu tidak berubah?
JSR
16

Untuk menghapus berdasarkan nilai:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))
Prakhar Pandey
sumber
Pertanyaannya adalah tentang menghapus item berdasarkan indeks , bukan menghapus item dengan nilai tertentu
Sherzod
5

Tidak menjadi orang yang numpy, saya mengambil foto dengan:

>>> import numpy as np
>>> import itertools
>>> 
>>> a = np.array([1,2,3,4,5,6,7,8,9])
>>> index=[2,3,6]
>>> a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))
>>> a
array([1, 2, 5, 6, 8, 9])

Menurut tes saya, ini mengungguli numpy.delete(). Saya tidak tahu mengapa itu akan terjadi, mungkin karena ukuran kecil array awal?

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
100000 loops, best of 3: 12.9 usec per loop

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "np.delete(a, index)"
10000 loops, best of 3: 108 usec per loop

Itu perbedaan yang cukup signifikan (berlawanan arah dengan apa yang saya harapkan), ada yang tahu mengapa ini akan terjadi?

Yang lebih aneh, melewati numpy.delete()daftar berkinerja lebih buruk daripada mengulang-ulang daftar dan memberikannya indeks tunggal.

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "for i in index:" "    np.delete(a, i)"
10000 loops, best of 3: 33.8 usec per loop

Sunting: Tampaknya memang ada hubungannya dengan ukuran array. Dengan array besar, numpy.delete()secara signifikan lebih cepat.

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
10 loops, best of 3: 200 msec per loop

python -m timeit -s "import numpy as np" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "np.delete(a, index)"
1000 loops, best of 3: 1.68 msec per loop

Jelas, ini semua sangat tidak relevan, karena Anda harus selalu mencari kejelasan dan menghindari menciptakan kembali roda, tetapi saya menemukan itu sedikit menarik, jadi saya pikir saya akan meninggalkannya di sini.

Gareth Latty
sumber
2
Berhati-hatilah dengan apa yang sebenarnya Anda bandingkan! Anda memiliki a = delte_stuff(a)iterasi pertama Anda, yang membuatnya alebih kecil dengan setiap iterasi. Ketika Anda menggunakan fungsi inbuild, Anda tidak menyimpan nilai kembali ke, yang membuat ukuran aslinya! Selain itu, Anda dapat mempercepat fungsi Anda secara drastis, saat Anda membuat kumpulan indexdan mengeceknya, apakah akan menghapus item atau tidak. Memperbaiki kedua hal, saya dapatkan untuk 10k item: 6,22 msec per loop dengan fungsi Anda, 4,48 msec untuk numpy.delete, yang kira-kira seperti apa yang Anda harapkan.
Michael
2
Dua petunjuk lagi: Alih-alih np.array(list(range(x)))digunakan np.arange(x), dan untuk membuat indeks, Anda dapat menggunakan np.s_[::2].
Michael
1

Jika Anda tidak tahu indeksnya, Anda tidak bisa menggunakannya logical_and

x = 10*np.random.randn(1,100)
low = 5
high = 27
x[0,np.logical_and(x[0,:]>low,x[0,:]<high)]
idnavid
sumber
1

Menggunakan np.deleteadalah cara tercepat untuk melakukannya, jika kita tahu indeks elemen yang ingin kita hapus. Namun, untuk kelengkapan, izinkan saya menambahkan cara lain "menghapus" elemen array menggunakan topeng boolean yang dibuat dengan bantuan np.isin. Metode ini memungkinkan kami untuk menghapus elemen dengan menentukan secara langsung atau dengan indeks mereka:

import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

Hapus berdasarkan indeks :

indices_to_remove = [2, 3, 6]
a = a[~np.isin(np.arange(a.size), indices_to_remove)]

Hapus berdasarkan elemen (jangan lupa untuk membuat ulang yang asli akarena sudah ditulis ulang di baris sebelumnya):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]
Andreas K.
sumber
0

Hapus indeks spesifik (saya menghapus 16 dan 21 dari matriks)

import numpy as np
mat = np.arange(12,26)
a = [4,9]
del_map = np.delete(mat, a)
del_map.reshape(3,4)

Keluaran:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])
Raja Ahsan Zeb
sumber
0

Anda juga dapat menggunakan set:

a = numpy.array([10, 20, 30, 40, 50, 60, 70, 80, 90])
the_index_list = [2, 3, 6]

the_big_set = set(numpy.arange(len(a)))
the_small_set = set(the_index_list)
the_delta_row_list = list(the_big_set - the_small_set)

a = a[the_delta_row_list]
OlDor
sumber