Эффективное удаление строк в NumPy - PullRequest
2 голосов
/ 28 августа 2011

У меня есть большой массив с множеством значений ID (назовите его X):

X:
id   rating
1    88
2    99
3    77
4    66
...

и т. Д.У меня также есть еще один массив «плохих идентификаторов», которые обозначают строки, которые я хотел бы удалить из X.

B: [2, 3]

Поэтому, когда я закончу, я бы хотел:

X:
id   rating
1    88
4    66

Какой самый чистый способ сделать это, не повторяя?

Ответы [ 3 ]

8 голосов
/ 28 августа 2011

Это самый быстрый способ, которым я мог придумать:

import numpy

x = numpy.arange(1000000, dtype=numpy.int32).reshape((-1,2))
bad = numpy.arange(0, 1000000, 2000, dtype=numpy.int32)

print x.shape
print bad.shape

cleared = numpy.delete(x, numpy.where(numpy.in1d(x[:,0], bad)), 0)
print cleared.shape

Это печатает:

(500000, 2)
(500,)
(499500, 2)

и работает намного быстрее, чем уфунк. Он будет использовать некоторую дополнительную память, но будет ли это нормально для вас, зависит от размера вашего массива.

Пояснение:

  • numpy.in1d ​​ возвращает массив того же размера, что и x содержащий True, если элемент находится в массиве bad, и False в противном случае.
  • numpy.where превращает этот массив True / False в массив целых чисел, содержащий значения индекса, где массив был True.
  • Затем он передает местоположения индекса в numpy.delete , приказывая удалить по первой оси (0)
2 голосов
/ 28 августа 2011

воспроизводит спецификацию проблемы из OP:

X = NP.array('1 88 2 99 3 77 4 66'.split(), dtype=int).reshape(4, 2)
bad_ids = [3,2]
bad_ideas = set(bad_ideas)    # see jterrance comment below this Answer

Векторизация встраивание из тестов членства Python - то есть X в синтаксисе Y

@NP.vectorize
def filter_bad_ids(id) :
    return id not in bad_ids


>>> X_clean = X[filter_bad_ids(X[:,0])]
>>> X_clean                                # result
   array([[ 1, 88],
          [ 4, 66]])
0 голосов
/ 30 октября 2015

Если вы хотите полностью удалить информацию для плохих идентификаторов, попробуйте это:

x = x[numpy.in1d(x[:,0], bad, invert=True)]

Это решение использует довольно мало памяти и должно быть очень быстрым. (bad преобразуется в пустой массив, поэтому не должен быть установлен для этого, см. примечание в http://docs.scipy.org/doc/numpy/reference/generated/numpy.in1d.html)
Если плохо очень мало, вместо этого это может быть немного быстрее:

from functools import reduce
x = x[~reduce(numpy.logical_or, (x[:,0] == b for b in bad))]

Примечание: первая строка требуется только в Python3.
Это также использует мало памяти из-за использования генератора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...