【问题标题】:intersection of np.array and setnp.array 和集合的交集
【发布时间】:2016-08-09 01:20:24
【问题描述】:

我想将 np.array 与集合相交,而不必先将 np.array 转换为列表(将程序减慢到无法运行的水平)。

这是我当前的代码:(请注意,我从 b,g,r rawCapture 获取这些数据,而 selection_data 只是预先设置的一个集合。)

def GreenCalculations(data):
    data.reshape(1,-1,3)
    data={tuple(item) for item in data[0]}
    ColourCount=selection_data & set(data)
    Return ColourCount

现在我认为我目前的问题是我只比较图片的第一部分,由于数据[0]。是否可以循环遍历所有行?

注意:tolist() 需要很多时间。

【问题讨论】:

    标签: python arrays python-2.7 numpy set


    【解决方案1】:

    首先是一个样本data;我猜这是一个 nxnx3 数组,dtype uint8

    In [791]: data=np.random.randint(0,256,(8,8,3),dtype=np.uint8)
    

    reshape 方法返回一个具有新形状的新数组,但不会就地改变它:

    In [793]: data.reshape(1,-1,3)
    

    data.shape=(1,-1,3) 会就地执行此操作。但为什么是最初的1

    改为:

    In [795]: aset={tuple(item) for item in data.reshape(-1,3)}
    In [796]: aset
    Out[796]: 
    {(3, 92, 60),
     (5, 211, 227),
     (6, 185, 183),
     (9, 37, 0),
     ....
    
     In [797]: len(aset)
     Out[797]: 64
    

    在我的例子中,一组 64 个独特的项目 - 考虑到我是如何生成这些值的,这并不奇怪

    您的无所事事 data.reshape 行和 {tuple(item) for item in data[0]} 解释了为什么它似乎只在图片的第一行工作。

    我猜selection_data是类似的3项元组,比如:

    In [801]: selection_data = {tuple(data[1,3,:]), (1,2,3), tuple(data[5,5,:])}
    In [802]: selection_data
    Out[802]: {(1, 2, 3), (49, 132, 26), (76, 131, 16)}
    In [803]: selection_data&aset
    Out[803]: {(49, 132, 26), (76, 131, 16)}
    

    你没有说你在哪里尝试使用tolist,但我猜是在生成元组集。

    但奇怪的是,tolist 加快了转换速度:

    In [808]: timeit {tuple(item) for item in data.reshape(-1,3).tolist()}
    10000 loops, best of 3: 57.7 µs per loop
    In [809]: timeit {tuple(item) for item in data.reshape(-1,3)}
    1000 loops, best of 3: 239 µs per loop
    In [815]: timeit data.reshape(-1,3).tolist()
    100000 loops, best of 3: 19.8 µs per loop
    In [817]: timeit {tuple(item.tolist()) for item in data.reshape(-1,3)}
    10000 loops, best of 3: 100 µs per loop
    

    所以做这种list和set操作,我们还不如直接跳到list格式。

    numpy 有一些设置函数,例如np.in1d。这只对一维数组进行操作,但正如在一些unique row 问题中所展示的那样,我们可以通过将二维数组视为结构化数组来解决这个问题。我不得不摆弄才能走到这一步:

    In [880]: dt=np.dtype('uint8,uint8,uint8')
    In [881]: data1=data.reshape(-1,3).view(dt).ravel()
    In [882]: data1
    Out[882]: 
    array([(41, 145, 254), (138, 144, 7), (192, 241, 203), (42, 177, 215),
           (78, 132, 87), (221, 176, 87), (107, 171, 147), (231, 13, 53),
           ... 
          dtype=[('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1')])
    

    构造一个具有相同结构化数组性质的选择:

    In [883]: selection=[data[1,3,:],[1,2,3],data[5,5,:]]
    In [885]: selection=np.array(selection,np.uint8).view(dt)
    In [886]: selection
    Out[886]: 
    array([[(49, 132, 26)],
           [(1, 2, 3)],
           [(76, 131, 16)]], 
          dtype=[('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1')])
    

    所以selection 中的项目也可以在data1 中找到:

    In [888]: np.in1d(selection,data1)
    Out[888]: array([ True, False,  True], dtype=bool)
    

    data1 中选择的项目是:

    In [890]: np.where(np.in1d(data1,selection))
    Out[890]: (array([11, 45], dtype=int32),)
    

    或未解开的形状

    In [891]: np.where(np.in1d(data1,selection).reshape(8,8))
    Out[891]: (array([1, 5], dtype=int32), array([3, 5], dtype=int32))
    

    我用来生成 selection 的相同 (1,3) 和 (5,5) 项。

    in1d 的时间竞争激烈:

    In [892]: %%timeit
         ...: data1=data.reshape(-1,3).view(dt).ravel()
         ...: np.in1d(data1,selection)
         ...: 
    10000 loops, best of 3: 65.7 µs per loop
    
    In [894]: timeit selection_data&{tuple(item) for item in data.reshape(-1,3).tolist()}
    10000 loops, best of 3: 91.5 µs per loop
    

    【讨论】:

    • 预计tolist会加快转化速度。 Numpy 对象将数据存储为原始值,而不是 python 对象。这意味着来自 python 的每次访问都需要 numpy 为该值创建一个包装器对象。这也在迭代时完成。 tolist 方法在一个优化的 C 循环中创建所有包装器并将它们放入一个 python 列表中,随后的迭代在一个 python 列表上进行,这很快,因为它不必创建包装器对象。
    【解决方案2】:

    如果我正确理解了您的问题(并且我不能 100% 确定我这样做;但使用与 hpaulj 相同的假设),您的问题可以通过使用 numpy_indexed 包来解决:

    import numpy_indexed as npi
    ColourCount = npi.intersection(data.reshape(-1, 3), np.asarray(selection_data))
    

    也就是说,它将重构后的数组和集合都视为长度为 3 的 ndarray 的序列,它以向量化的方式找到其中的交集。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 2012-01-26
      相关资源
      最近更新 更多