Как удалить определенные элементы в массиве NumPy


212

Как я могу удалить некоторые конкретные элементы из массива NumPy? Скажи у меня есть

import numpy as np

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

Затем я хочу удалить 3,4,7из a. Все, что я знаю, это индекс значений ( index=[2,3,6]).

Ответы:


287

Использовать 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
@ Левон, можешь добавить примеры для 2D?
MattS

7
@IngviGautsson Ты не прав. Для этого нужны индексы удаляемых предметов, а не сами предметы.
Le Frite

64

Существует встроенная функция NumPy, чтобы помочь с этим.

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 будет медленнее, но, увы, timeit для 1000 целых чисел говорит, что delete в x2 быстрее.
WBG

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

Это также сортирует вывод, который может не соответствовать желаемому. В остальном очень мило.
Райзинц

Вопрос говорит: «Все, что я знаю, это индекс ценностей». Итак, речь идет об удалении элементов по их индексам , а не с их значениями
Шерзод

35

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

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

1
+1 за упоминание «неизменного».
Полезно

38
технически, массивы numy являются изменяемыми. Например, это: 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, которое сохраняет исходный размер! Кроме того, вы можете резко ускорить свою функцию, когда создаете набор функций 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.