派手な配列の特定の要素を削除する方法


212

どうすれば派手な配列から特定の要素を削除できますか?私が持っていると言います

import numpy as np

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

次に、から削除3,4,7aます。私が知っているのは、値のインデックス(index=[2,3,6])だけです。

回答:


284

numpy.delete()を使用- 軸に沿ったサブ配列が削除された新しい配列を返します

numpy.delete(a, index)

特定の質問について:

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

配列スカラーは不変で、Pythonの文字列に似ているnumpy.delete()ため、新しい配列を返すことに注意してください。そのため、変更が行われるたびに、新しいオブジェクトが作成されます。つまり、ドキュメントを引用するには:delete()

「objで指定された要素が削除されたarr のコピー削除はインプレースでは発生しないことに注意してください ...」

私が投稿したコードに出力がある場合、それはコードを実行した結果です。


1
@IngviGautsson編集を行ったときに、要素の正しい値も2、3、6から3、4、7に変更しました。コードを実行すると、元々あった正しい出力が得られません。I "m編集をロールバックします
Levon

1
AttributeError: 'list'オブジェクトに属性 'delete'がありません
munmunbb

3
@IngviGautssonいいえ、あなたのコメントは誤解を招くものです。これは期待どおりに機能します。ただし、numpy.delete()のドキュメントには、「多くの場合、ブールマスクを使用することが望ましい」と記載されています。その例も示します。
Biggsy、

1
@Levonは2Dの例を追加できますか?
MattS

7
@IngviGautssonあなたは間違っている。削除するアイテム自体のインデックスではなく、アイテムのインデックスを取得します。
Le Frite、

64

それを手助けするための派手な組み込み関数があります。

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
知っておくと良い。np.deleteは遅くなると思っていましたが、悲しいかな、1000整数のtimeitはdeleteがx2速いと言っています。
wbg 2016年

1
削除したいインデックス/インデックスを提供する必要がなく、配列の値を操作するので、これは素晴らしいことです。次に例を示しますnp.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
。– MD004

これはまた、出力をソートしますが、これは必要なものではない可能性があります。そうでなければとてもいい。
rayzinnz

質問は、「私が知っているのは値のインデックスだけです」と言っています。だから、それはについてですそのインデックスによって項目を削除、それらの値を除去しない、
Sherzod

35

Numpy配列は不変です。つまり、技術的には項目を削除できません。ただし、次のように、不要値なしで新しい配列を作成できます。

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

1
「不変」に言及するための+1。numpy配列はサイズの迅速な変更(要素の追加/削除)には
適さないことに注意してください

38
技術的には、numpy配列は変更可能です。たとえば、次のようにa[0]=1変更aします。ただし、サイズを変更することはできません。
btel 2014年

3
定義はその不変を示していますが、新しい値を割り当てることで変更できる場合、それはどのように不変ですか?
JSR

16

値で削除するには:

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

質問は約あるインデックスでアイテムを削除する特定の値を持つ項目を削除しない、
Sherzod

5

派手な人間ではないので、私は次のことを試してみました:

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

私のテストによると、これはを上回っていnumpy.delete()ます。初期配列のサイズが小さいためか、なぜそうなるのかわかりません。

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

これはかなり大きな違いです(私が期待していたのとは逆の方向です)。なぜこれが当てはまるのか、だれでも知っていますか?

さらに奇妙なことにnumpy.delete()、リストを渡すと、リストをループして単一のインデックスを与えるよりもパフォーマンスが低下します。

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

編集:配列のサイズに関係しているようです。大規模な配列でnumpy.delete()は、大幅に高速です。

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

明らかに、これはかなり重要ではありません。常に明確にするために行き、ホイールを再発明しないようにする必要がありますが、私は少し興味深いことに気づいたので、ここには残しておきたいと思いました。


2
実際に比較するものに注意してください!あなたは持っていa = delte_stuff(a)ますあなたの最初の反復でaすべての反復と小さいです。inbuild関数を使用する場合、値をaに格納しないで、aを元のサイズに保ちます。その上、関数を大幅に高速化できます。indexつまり、アイテムの削除の有無にかかわらず、セットoufを作成し、それに対してチェックします。両方を修正すると、1万アイテムが得られます。関数ではループあたり6.22ミリ秒、では4.48ミリ秒ですnumpy.delete。これは、おおよその予想値です。
Michael

2
さらに2つのヒント:をnp.array(list(range(x)))使用する代わりにnp.arange(x)、インデックスを作成するためにを使用できますnp.s_[::2]
Michael

1

インデックスがわからない場合は使用できません 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.delete削除する要素のインデックスがわかっている場合は、使用するのが最も速い方法です。ただし、完全を期すために、を使用して作成されたブールマスクを使用して配列要素を「削除」する別の方法を追加しますnp.isin。このメソッドを使用すると、要素を直接またはインデックスで指定して、要素を削除できます。

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

インデックスで削除

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

要素ごとに削除a前の行で書き直されたので、オリジナルを再作成することを忘れないでください):

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

0

特定のインデックスを削除します(マトリックスから16と21を削除しました)

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

出力:

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

0

セットを使用することもできます。

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]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.