【问题标题】:Remove numpy rows contained in a list?删除列表中包含的 numpy 行?
【发布时间】:2018-10-04 06:07:38
【问题描述】:

我有一个 numpy 数组和一个列表。我想删除列表中包含的行。

a = np.zeros((3, 2))
a[0, :] = [1, 2]
l = [(1, 2), (3, 4)]

目前我尝试通过创建一组a 的行来做到这一点,然后排除从l 创建的set,类似于:

sa = set(map(tuple, a))
sl = set(l)
np.array(list(sa - sl))

或者更简单

sl = set(l)
np.array([row for row in list(map(tuple, a)) if row not in sl]

当每一行都很短时,这些效果很好。

有没有更快的方法?我需要优化速度。

【问题讨论】:

  • 看看np.lib.arraysetops函数
  • @hpaulj 我明白了,np.lib.arraysetops 是通过排序模拟的set。但是与直接在python中创建集合相比如何?我想对于长数组和列表,使用set 更快?

标签: python arrays performance numpy set


【解决方案1】:

方法#1:这是views(将每一行视为一个元素,每个元素都具有扩展的dtype)-

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

a1D,l1D = view1D(a,l)
out = a[np.in1d(a1D,l1D,invert=True)]

如果您只需要像set 那样在输出中拥有唯一行,请在获得的输出上使用np.unique -

np.unique(out,axis=0)

样本运行输出 -

In [72]: a
Out[72]: 
array([[1, 2],
       [0, 0],
       [0, 0]])

In [73]: l
Out[73]: [(1, 2), (3, 4)]

In [74]: out
Out[74]: 
array([[0, 0],
       [0, 0]])
In [75]: np.unique(out,axis=0)
Out[75]: array([[0, 0]])

方法 #2: 具有相同的降维理念,这里是针对 int dtype 数据的矩阵乘法 -

l = np.asarray(l)
shp = np.maximum(a.max(0)+1,l.max(0)+1)
s = np.r_[shp[::-1].cumprod()[::-1][1:],1]
l1D = l.dot(s)
a1D = a.dot(s)
l1Ds = np.sort(l1D)
out = a[l1D[np.searchsorted(l1Ds,a1D)] != a1D]

【讨论】:

  • 谢谢。但是代码看起来相当复杂,不容易理解。我没有看到散列的使用。它如何提高速度?
  • @THN 它通过降低维度来提高性能。每一行都作为一个“实体”处理。这里没有散列,反正也不是明确的。
  • 我明白了,所以view1Ddot 是一种减少需要比较的方法。这可以与以后的搜索区分开来。排序 + 二进制搜索与散列是另一个取决于特定数据的问题。谢谢。
猜你喜欢
  • 2014-03-18
  • 2020-11-27
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2018-05-13
  • 2022-01-07
相关资源
最近更新 更多