Индексирование чисел: возвращение остальных
Простой пример индексирования numpy:
In: a = numpy.arange(10)
In: sel_id = numpy.arange(5)
In: a[sel_id]
Out: array([0,1,2,3,4])
Как вернуть остальную часть массива, которая не индексируется sel_id? Я могу подумать:
In: numpy.array([x for x in a if x not in a[id]])
out: array([5,6,7,8,9])
Есть ли более простой способ?
Ответы
Ответ 1
Для этого простого случая 1D я бы использовал логическую маску:
a = numpy.arange(10)
include_index = numpy.arange(4)
include_idx = set(include_index) #Set is more efficient, but doesn't reorder your elements if that is desireable
mask = numpy.array([(i in include_idx) for i in xrange(len(a))])
Теперь вы можете получить свои значения:
included = a[mask] # array([0, 1, 2, 3])
excluded = a[~mask] # array([4, 5, 6, 7, 8, 9])
Обратите внимание, что a[mask]
не обязательно дает то же самое, что и a[include_index]
, так как порядок include_index
имеет значение для вывода в этом сценарии (он должен быть примерно эквивалентен a[sorted(include_index)]
). Однако, поскольку порядок ваших исключенных элементов не определен, это должно работать нормально.
ИЗМЕНИТЬ
Лучший способ создать маску:
mask = np.zeros(a.shape,dtype=bool)
mask[include_idx] = True
(благодаря seberg).
Ответ 2
Вы можете сделать это с помощью булевых масок:
a = numpy.arange(10)
mask = np.ones(len(a), dtype=bool) # all elements included/True.
mask[[7,2,8]] = False # Set unwanted elements to False
print a[mask]
# Gives (removing entries 7, 2 and 8):
[0 1 3 4 5 6 9]
Дополнение (взято из @mgilson). Созданная двоичная маска может использоваться красиво, чтобы вернуть исходные фрагменты с помощью a[~mask]
, но это все равно, если исходные индексы были отсортированы.
ИЗМЕНИТЬ: Сдвиг вниз, так как я должен был понять, что в это время я рассмотрю багги np.delete
(сентябрь 2012 г.).
Вы также можете использовать np.delete
, хотя маски более мощные (и в будущем я думаю, что это должен быть вариант OK). В настоящий момент, однако, это медленнее, чем указано выше, и создаст неожиданные результаты с отрицательными индексами (или шагами при предоставлении среза).
print np.delete(a, [7,2,8])
Ответ 3
Это больше похоже:
a = numpy.array([1, 2, 3, 4, 5, 6, 7, 4])
exclude_index = numpy.arange(5)
include_index = numpy.setdiff1d(numpy.arange(len(a)), exclude_index)
a[include_index]
# array([6, 7, 4])
# Notice this is a little different from
numpy.setdiff1d(a, a[exclude_index])
# array([6, 7]
Ответ 4
Я бы сделал это с булевой маской, но немного по-другому. Это полезно для работы в N-образных размерах, с непрерывными или нет индексами. Использование памяти будет зависеть от того, создается ли представление или копия для маскированного массива, и я не уверен.
import numpy
a = numpy.arange(10)
sel_id = numpy.arange(5)
mask = numpy.ma.make_mask_none(a.shape)
mask[sel_id] = True
answer = numpy.ma.masked_array(a, mask).compressed()
print answer
# [5 6 7 8 9]
Ответ 5
Кроме того, если они смежны, используйте синтаксис [N:], чтобы выбрать остальные. Например, arr [5:] будет выбирать от 5 до последнего элемента в массиве.
Ответ 6
numpy.setdiff1d(a, a[sel_id])
должен сделать трюк. Не знаю, есть ли что-то более аккуратное, чем это.
Ответ 7
Предполагая, что a
является 1D-массивом, вы можете просто поместить элементы, которые вы не хотите из списка индексов:
accept = [i for i in range(a.size) if i not in avoid_list]
a[accept]
Вы также можете попытаться использовать что-то вроде
accept = sorted(set(range(a.size)) - set(indices_to_discard))
a[accept]
Идея заключается в использовании причудливой индексации на дополнении к набору индексов, которые вы не хотите.