删除频率较低的项目

时间:2015-08-01 13:48:21

标签: python numpy

让我们考虑长度为n的数组:

y=np.array([1,1,1,1,2,2,2,3,3,3,3,3,2,2,2,2,1,4,1,1,1])

以及尺寸为X x n的矩阵m

我想删除yX行的项目,y的相应值频率较低。

我发现这会给我y的值,应删除:

>>> items, count = np.unique(y, return_counts=True)
>>> to_remove = items[count < 3]                           # array([4])

这将删除项目:

>>> X=X[y != to_remove,:]
>>> y=y[y != to_remove]
array([1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1])

虽然只有一个要删除的标签时上述代码有效,但当y的多个值频率较低时,它会失败(即y=np.array([1,1,1,1,2,2,2,3,3,3,3,3,2,2,2,2,1,4,1,1,1,5,5,1,1])会导致to_remove成为array([4, 5]) {1}}):

>>> y[y != to_remove,:]
Traceback (most recent call last):
  File "<input>", line 1, in <module>
IndexError: too many indices for array

如何以简洁的方式解决这个问题?

3 个答案:

答案 0 :(得分:2)

您可以在np.unique中使用其他输出参数return_inverse,如此 -

def unique_where(y):
    _, idx, count = np.unique(y, return_inverse=True,return_counts=True)
    return y[np.in1d(idx,np.where(count>=3)[0])]

def unique_arange(y):
    _, idx, count = np.unique(y, return_inverse=True,return_counts=True)
    return y[np.in1d(idx,np.arange(count.size)[count>=3])] 

你可以使用np.bincount来计算在计算时非常有效的计数,并且在这里可能更适合它,假设y包含非负数,就像这样 -

def bincount_where(y):
    counts = np.bincount(y)
    return y[np.in1d(y,np.where(counts>=3)[0])]

def bincount_arange(y):
    counts = np.bincount(y)
    return y[np.in1d(y,np.arange(y.max())[counts>=3])]

运行时测试 -

本节将列出上述三种方法以及@Ashwini Chaudhary's solution -

中列出的方法
In [85]: y = np.random.randint(0,100000,50000)

In [90]: def unique_items_indexed(y): # @Ashwini Chaudhary's solution
        ...:     items, count = np.unique(y, return_counts=True)
        ...:     return y[np.in1d(y, items[count >= 3])]
        ...: 

In [115]: %timeit unique_items_indexed(y)
10 loops, best of 3: 19.8 ms per loop

In [116]: %timeit unique_where(y)
10 loops, best of 3: 26.9 ms per loop

In [117]: %timeit unique_arange(y)
10 loops, best of 3: 26.5 ms per loop

In [118]: %timeit bincount_where(y)
100 loops, best of 3: 16.7 ms per loop

In [119]: %timeit bincount_arange(y)
100 loops, best of 3: 16.5 ms per loop

答案 1 :(得分:1)

如果to_remove中有多个值,则操作定义不正确:

>>> to_remove
array([4, 5])
>>> y != to_remove
True

使用运算符in1d

>>> ~np.in1d(y, to_remove)
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True, False,
        True,  True,  True, False, False,  True,  True], dtype=bool)

答案 2 :(得分:1)

您正在寻找numpy.in1d

>>> y = np.array([1,1,1,1,2,2,2,3,3,3,3,3,2,2,2,2,1,4,1,1,1,5,5,1,1])
>>> items, count = np.unique(y, return_counts=True)
>>> to_remove = items[count < 3]
>>> y[~np.in1d(y, to_remove)]
array([1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1])