Як видалити конкретні елементи з масиву numpy


212

Як я можу видалити деякі конкретні елементи з масивного ряду? Скажи, що я

import numpy as np

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

Потім я хочу видалити 3,4,7з a. Все, що я знаю, - це індекс значень ( index=[2,3,6]).

Відповіді:


285

Використовувати 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]`

Зауважте, що numpy.delete()повертає новий масив, оскільки скаляри масивів є незмінними, подібно до рядків у Python, тому щоразу, коли до нього вносяться зміни, створюється новий об'єкт. Тобто, щоб процитувати delete() документи :

"Видалена копія arr з елементами, вказаними obj. Зауважте, що видалення не відбувається на місці ..."

Якщо код, який я публікую, має вихід, це результат запуску коду.


1
@IngviGautsson Під час редагування ви також змінили правильні значення елементів з 2, 3, 6 до 3, 4, 7, якщо запустити код зараз, ви не отримаєте правильного виводу, як це було раніше. "Відкат редагування
Левон

1
AttributeError: об’єкт 'list' не має атрибута 'delete'
munmunbb

3
@IngviGautsson Ні, ваш коментар вводить в оману. Це працює як очікувалося. Однак у документації numpy.delete () зазначається, що "часто краще використовувати булева маска"; також наведено приклад цього.
Biggsy

1
@Levon чи можете ви додати приклади для 2D?
Метс

7
@IngviGautsson Ви помиляєтесь. Для видалення потрібні індекси елементів, а не самі елементи.
Le

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 цілих чисел каже, що видалити x2 швидше.
wbg

1
Це здорово , тому що він працює на масив значень , замість того , щоб забезпечити індекс / індекси , які ви хочете видалити. Наприклад:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004

Це також сортує вихід, який може бути не тим, що потрібно. Інакше дуже приємно.
rayzinnz

Питання говорить "Все, що я знаю, - це індекс значень". Отже, мова йде про видалення елементів за їх індексами , а не про видалення їх значень
Шерзод,

35

Масив Numpy незмінний , це означає, що ви технічно не можете видалити елемент з нього. Однак ви можете побудувати новий масив без значень, які вам не потрібні, наприклад:

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

1
+1 за згадування "незмінного". Добре пам’ятати, що нумеровані масиви не підходять для швидкої зміни розміру (додавання / видалення елементів)
eumiro

38
технічно нумеровані масиви змінюються. Наприклад, це: a[0]=1змінюється aна місці. Але їх не можна змінити.
btel

3
Визначення говорить про його незмінності, але якщо присвоєння нового значення дозволить вам змінити, то як це незмінне?
JSR

16

Щоб видалити за значенням:

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

Питання полягає у видаленні елементів за індексами , а не про видаленні елементів із конкретним значенням
Шерзод

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з кожною ітерацією стає меншою. Використовуючи функцію вбудови, ви не зберігаєте значення в a, що зберігає a в оригінальному розмірі! Крім того, ви можете значно прискорити свою функцію, створивши набір indexі перевірити, чи потрібно видаляти елемент чи ні. Виправляючи обидві речі, я отримую за 10 к. Елементів: 6,22 мсек за цикл зі своєю функцією, 4,48 мсек для numpy.delete, що приблизно те, що ви очікували.
Майкл

2
Ще два підказки: Замість np.array(list(range(x)))використання np.arange(x)та для створення індексу можна використовувати np.s_[::2].
Майкл

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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.