高效删除NumPy中的行
我有一个很大的numpy数组,里面有很多ID值(我们叫它X):
X:
id rating
1 88
2 99
3 77
4 66
...
等等。我还有另一个numpy数组,里面是一些“坏ID”——这些ID代表我想从X中删除的行。
B: [2, 3]
所以最后,我想要的是:
X:
id rating
1 88
4 66
有没有什么简单的方法可以做到这一点,而不需要一个一个地去处理?
3 个回答
0
如果你想彻底删除不好的ID的信息,可以试试这个方法:
x = x[numpy.in1d(x[:,0], bad, invert=True)]
这个方法用的内存比较少,而且速度应该很快。(这里的bad被转换成了一个numpy数组,所以为了让这个方法有效,bad不能是一个集合,具体可以参考这个链接)
如果bad的数量非常少,使用下面的方法可能会更快:
from functools import reduce
x = x[~reduce(numpy.logical_or, (x[:,0] == b for b in bad))]
注意:第一行代码在Python3中是必须的。
这个方法也用的内存不多,因为它使用了生成器。
2
重现原作者提到的问题:
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 in 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]])
8
这是我想到的最快的方法:
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)
而且运行速度比 ufunc 快很多。它会使用一些额外的内存,但这是否可以接受取决于你的数组有多大。
解释:
- numpy.in1d 会返回一个和
x
一样大小的数组,如果某个元素在bad
数组里,就返回True
,否则返回False
。 - numpy.where 会把这个
True
/False
的数组转换成一个整数数组,里面包含了所有True
的索引位置。 - 然后,它会把这些索引位置传给 numpy.delete,告诉它沿着第一个轴(0轴)删除对应的元素。