【问题标题】:Numpy: Remove neighboring repeated subarrays in a 2x2 array?Numpy:删除2x2数组中相邻的重复子数组?
【发布时间】:2014-01-02 21:23:13
【问题描述】:

好的,我是 Numpy 的新手,但我无法弄清楚这一点,所以把它交给专家。我有一个像下面这样的 2x2 表数组,我想“顺序唯一化”该数组。顺序很重要,因此如果有多个相同的行数组彼此相邻,那么它们是多余的,应该被排除在外(行数组的顺序也很重要,因此 [111,222] 将被视为不同的 [222,111])。以另一种方式构建,我只想保留其左右邻居(或如下所示的顶部/底部)与其自身不同的行数组(在下面的示例中由 * 标记)。

[[[492 105]
  [492 105]
  [492 105]*
  [492 106]*
  [492 106]
  [492 106]
  [491 106]*
  [491 106]
  [491 105]*
  [491 105]
  [491 105]
  [492 105]*
  [492 105]
  [492 105]]]

我尝试了 numpy.uniquify 函数,但它并不关心我有一个 2x2 数组的事实,而是在我不想要的平面列表中返回每个子数组中的每个唯一数字,它排序并更改了顺序我也不想要的原始数组。

通过一个简单的 for 循环,我可以很容易地写出它的逻辑,但我需要以 Numpy 的速度对其进行优化。我得到的最接近的是返回一个真值数组,标记左邻居不同的点,这似乎正在工作:

MYARRAY = numpy.matrix(  my2x2array  )
indexes = numpy.arange(len(MYARRAY))
trutharray = numpy.any(MYARRAY[indexes]!=MYARRAY[indexes-1], 1)

但是,我不确定如何进行以及如何处理真值数组。尝试将真值数组提供给 numpy.extract 函数,但这仅返回每个子数组的平面列表,甚至不返回它应该返回的所有元素;在我的示例中,它返回“[105 492 492 106]”。

有什么帮助吗?如何继续我的示例并最终得到唯一的顺序子数组?或者有没有更快的解决方案来解决这个问题? Numpy 在这个阶段让我很困惑:p

【问题讨论】:

    标签: python numpy multidimensional-array unique


    【解决方案1】:

    我猜是这样的:

    >>> a=array( [[492, 105],
    ...   [492, 105],
    ...   [492, 105],
    ...   [492, 106],
    ...   [492, 106],
    ...   [492, 106],
    ...   [491, 106],
    ...   [491, 106],
    ...   [491, 105],
    ...   [491, 105],
    ...   [491, 105],
    ...   [492, 105],
    ...   [492, 105],
    ...   [492, 105]]
    ... )
    >>> g_idx=any(a[1:]!=a[:-1], axis=1)
    >>> vstack((a[:-1][g_idx][0], a[1:][g_idx]))
    array([[492, 105],
           [492, 106],
           [491, 106],
           [491, 105],
           [492, 105]])
    

    a[:-1][g_idx][0] 是必需的,否则第一个元素将丢失。

    【讨论】:

    • a[:-1][g_idx][0] 应该是a[0]
    • @CT Zhu,非常感谢您提供快速而直接的解决方案;它看起来是正确的,但并不完全正确。我打印了 vstack 操作的结果,发现输出返回了不同长度的子数组,但我需要子数组在原始子数组中(总是 2 个整数项)。那就是:对于我的原始示例,您的代码返回:[[492 492 491 491] [492 491 491 492]]。只返回我的子数组的左侧。
    • @BiRico,更改为 a[0] 导致错误,更改为 a[0] 也是如此:return _nx.concatenate(map(atleast_2d,tup),0) ValueError: array dimensions must agree except for d_0
    • 也许我提供了关于我的a 输入数组的错误信息。我使用了print a 并得到了[[492 105] [492 105] ..(middle omitted for clarity).. [492 105] [491 106]]a 由两个一维数组“newxs”和“newys”构造而成,代码为numpy.matrix(numpy.dstack((newxs,newys))) 另一个可能相关的信息是我的 Numpy 版本只有 v1.3。顺便说一句,你们的帮助很棒:)
    • 没关系,@CTZhu 你的回答确实是正确的。它对我不起作用,因为我误解了我的数组;我的数组数组已经在另一个数组[[[x,y],[x,y]...]] 中列出。所以我所要做的就是正确地改变我的数组,你的答案很完美,谢谢你,+1! a[0] 部分也适用于 BiRico。
    【解决方案2】:

    这可能比上面发布的解决方案稍微快一些;它通过预分配它消除了不必要的数组创建,它处理最后一个轴上的循环,以使用一些 voidview voodoo 以更快的方式检查所有元素是否不同。但除非我遗漏了什么,否则发布的解决方案应该接近最优,而且相当微不足道;我很难相信这确实是您代码中的瓶颈。

    import numpy as np
    
    a = np.array([[492, 105],
      [492, 105],
      [492, 105],
      [492, 106],
      [492, 106],
      [492, 106],
      [491, 106],
      [491, 106],
      [491, 105],
      [491, 105],
      [491, 105],
      [492, 105],
      [492, 105],
      [492, 105]])
    
    
    def voidview(arr):
        """view the last axis as a void object."""
        return np.ascontiguousarray(arr).view(np.dtype((np.void, arr.dtype.itemsize * arr.shape[-1]))).reshape(arr.shape[:-1])
    
    q = voidview(a)
    I = np.empty(len(q), np.bool)
    I[:-1] = q[1:]!=q[:-1]
    I[-1] = True
    print a[I]
    

    【讨论】:

    • 感谢@EelcoHoogendoorn,但正如您所说,改进只是微不足道的。为创意解决方案 +1 :)
    • 这是瓶颈之一,因为我的主要任务是在图片上绘制/渲染许多大多边形,我已经将坐标到像素的转换从渲染器中分离出来并手动进行在 numpy 中,我发现它更快。所以实际渲染只用了 1 秒,而坐标到像素的转换用了 30 秒(我们谈论的是非常大的多边形集合)。而这个独特的转换部分占用了大约 40% 的转换时间。另一个主要的瓶子是对 numpy 数组的实际计算。
    • 你在用python写软件渲染器吗?那么你需要的不仅仅是边际改进,是的;)。也许我错过了什么,但你到底为什么要这样做?
    • 呵呵,为了我自己和其他人,我正在尝试编写一个简单而快速的基于 Python 的包,人们可以使用它来查看/创建地理数据地图。我问过自己我是不是有点过头了,但我发现它有点需要,因为 PIL、Aggdraw、Matplotlib(基于 Aggdraw)甚至 PyCairo(如果我使用正确的话)都比我的慢当前的方法(使用 numpy 来最小化要处理的顶点)并且需要大量的技术技能。还没有尝试过 Mapnik,但据说它是基于 Pycairo 的。此外,我个人不喜欢 QGIS 的重量/复杂程度,所以我自己制作:P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 2019-12-31
    • 2020-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多