Numpy dizisindeki belirli öğeleri kaldırma


212

Bazı belirli öğeleri bir numpy dizisinden nasıl kaldırabilirim? Söyle bende

import numpy as np

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

Sonra kaldırmak istediğiniz 3,4,7dan a. Tek bildiğim değerler ( index=[2,3,6]) dizinidir .

Yanıtlar:


285

Numpy.delete () kullan - silinmiş bir eksen boyunca alt diziler içeren yeni bir dizi döndürür

numpy.delete(a, index)

Özel sorunuz için:

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

Dizi skalerleri Python'daki dizelere benzer şekilde değiştirilemediğinden numpy.delete()yeni bir dizi döndürdüğünü unutmayın , bu nedenle her değişiklik yapıldığında yeni bir nesne oluşturulur. Yani, belgeleri alıntılamak için :delete()

" Obj tarafından belirtilen öğelerin yer aldığı arr kopyası . Silme işleminin yerinde gerçekleşmediğini unutmayın ..."

Gönderdiğim kodun çıktısı varsa, kod çalıştırmanın sonucudur.


1
@IngviGautsson Düzenlemenizi yaptığınızda, 2, 3, 6'dan 3, 4, 7'ye öğeler için doğru değerleri de değiştirdiniz, eğer kodu çalıştırırsanız orijinal durumda olduğu gibi doğru çıktıyı alamazsınız. "Düzenlemeyi geri
Levon

1
AttributeError: 'list' nesnesinin 'delete' özelliği yok
munmunbb

3
@IngviGautsson Hayır, yorumunuz yanıltıcı. Bu beklendiği gibi çalışır. Bununla birlikte, numpy.delete () dokümantasyonu "genellikle bir boole maskesi kullanılması tercih edilir"; bunun bir örneği de verilmiştir.
Biggsy

1
@ Levon 2D için örnekler ekleyebilir misiniz?
Matt

7
@IngviGautsson Yanılıyorsunuz. Öğelerin kendileri değil, silinecek öğelerin indekslerini alır.
Le Frite

64

Bu konuda yardımcı olacak yerleşik bir fonksiyon var.

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

7
Bunu bildiğim iyi oldu. Ben np.delete daha yavaş olacağını düşünüyordum ama ne yazık ki, 1000 tamsayı için timeit silmek x2 daha hızlı olduğunu söylüyor.
wbg

1
Kaldırmak istediğiniz dizini / dizinleri sağlamak yerine dizinin değerleri üzerinde çalıştığı için bu harikadır . Örneğin:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004

Bu aynı zamanda çıktıyı da sıralar, bu da istenen şey olmayabilir. Aksi takdirde çok güzel.
rayzinnz

Soru "Bildiğim tek şey değerlerin dizinidir" diyor. Yani, öğeleri değerleriyle kaldırmak yerine dizinlerine göre kaldırmakla ilgilidir
Sherzod

35

Numpy dizisi değiştirilemez , yani teknik olarak bir öğeyi ondan silemezsiniz. Ancak, istemediğiniz değerler olmadan yeni bir dizi oluşturabilirsiniz, örneğin:

b = np.delete(a, [2,3,6])

1
'Değişmez' den bahsettiği için +1. Numpy dizilerin hızlı boyut değişiklikleri için (eleman ekleme / silme) iyi olmadığını hatırlamakta
fayda var

38
teknik olarak, numpy dizileri değiştirilebilir. Örneğin, bu: a[0]=1değiştirir ayerinde. Ancak yeniden boyutlandırılamazlar.
btel

3
Tanım değişmez olduğunu söylüyor, ancak yeni bir değer atayarak değiştirmenize izin veriyorsa, nasıl değişmez?
JSR

16

Değere göre silmek için:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))

Soru, belirli bir değere sahip öğeleri kaldırmak değil, dizinlere göre öğeleri kaldırmakla ilgilidir
Sherzod

5

Numpy olmayan biri olarak, bir çekim yaptım:

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

Testlerime göre, bu daha iyi performans gösteriyor numpy.delete(). Neden ilk dizi küçük boyutu nedeniyle, böyle olacağını bilmiyorum?

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

Bu oldukça önemli bir fark (beklediğimin tersi yönde), bunun neden böyle olacağına dair herhangi bir fikri olan var mı?

Daha da garip numpy.delete()bir şekilde, bir listeyi iletmek , listede dolaşmak ve listeye tekli indeksler vermekten daha kötü sonuç verir.

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

Düzenleme: Dizinin boyutu ile ilgili gibi görünüyor. Büyük dizilerle, numpy.delete()önemli ölçüde daha hızlıdır.

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

Açıkçası, her zaman netlik için gitmeli ve tekerleği yeniden icat etmekten kaçınmalısınız, ancak biraz ilginç buldum, bu yüzden burada bırakacağımı düşündüm.


2
Gerçekte ne karşılaştırdığınıza dikkat edin! Sen var a = delte_stuff(a)kılan ilk yineleme, içinde aher yineleme ile daha küçük. Inbuild işlevini kullandığınızda, değeri a boyutunda saklamazsınız, bu da a'yı orijinal boyutunda tutar! Bunun yanı sıra, indexbir öğe kümesi oluşturduğunuzda ve bir öğenin silinip silinmeyeceğini kontrol ettiğinizde işlevinizi önemli ölçüde hızlandırabilirsiniz . Her iki şeyi de sabitleyerek, 10k öğe için alıyorum: fonksiyonunuzla döngü başına 6.22 msn, 4.48 msn numpy.delete, kabaca beklediğiniz şey budur.
Michael

2
İki tane daha ipucu: Yerine np.array(list(range(x)))kullanımı np.arange(x)ve indeksi oluşturmak için kullanabileceğiniz np.s_[::2].
Michael

1

Dizini bilmiyorsanız, logical_and

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

1

np.deleteKaldırmak istediğimiz öğelerin indekslerini biliyorsanız, bunu yapmanın en hızlı yolu kullanmaktır . Ancak, tamlık için, yardımıyla oluşturulan bir boole maskesi kullanarak dizi öğelerini "kaldırmanın" başka bir yolunu eklememe izin verin np.isin. Bu yöntem, öğeleri doğrudan veya dizinleriyle belirterek kaldırmamızı sağlar:

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

Endekslere göre kaldır :

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

Öğelere göre kaldır (orijinali aönceki satırda yeniden yazıldığı için yeniden oluşturmayı unutmayın ):

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

0

Belirli dizini kaldır (16 ve 21'i matristen kaldırdım)

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

Çıktı:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])

0

Kümeleri de kullanabilirsiniz:

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]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.