【问题标题】:Index of the first and last numbers 1 of each column of an 2d array二维数组每列的第一个和最后一个数字 1 的索引
【发布时间】:2018-02-15 13:30:37
【问题描述】:

我有一个二维数组 (Q),仅包含零和一(二进制矩阵)。对于Q 的每一列,我想找到值 1 出现的第一行和最后一行的索引。每列至少包含一个1

这是一个例子:

[[1, 1, 1, 0, 0, 0, 0],
 [0, 1, 1, 1, 0, 0, 0],
 [1, 0, 0, 0, 1, 0, 1],
 [0, 0, 0, 1, 0, 1, 1],
 [1, 0, 1, 0, 0, 0, 0],
 [0, 0, 1, 0, 0, 0, 1],
 [0, 0, 0, 1, 0, 1, 0]]

boundsList = {0: (0, 4), 1: (0, 1), 2: (0, 5), 3: (1, 6), 4: (2, 2), 5: (3, 6), 6: (2, 5)}

我实现了一个算法,它可以工作,但是对于大型数组它效率不高:

boundsList = {}
for i in range (0, len(Q)):
    column = Q[:,i]
    indexesList = []
    for idx, pos in enumerate (column):
        if pos == 1:
            indexesList.append(idx)
    boundsList[i] = (indexesList[0], indexesList[-1])

任何人都可以为这个问题提出另一个简单的解决方案吗?

【问题讨论】:

  • 保证每一列至少有一个1?
  • 是的,至少会在该列中找到一个值 1。数组中只有值 0 和 1。
  • 谢谢先生们,所有提出的算法都优雅地解决了这个问题。

标签: python performance python-3.x numpy multidimensional-array


【解决方案1】:

可能最快的方法是从两侧使用argmax 方法(它之所以有效,是因为它找到了first最大值的位置),然后将其放入字典中。 argmax 方法的开销(常数因子)比使用 np.argmax 少得多,因此,特别是对于小型数组,该方法会快得多。

因为dictenumeratezip 在列表上比数组更快,所以我还将中间数组转换为列表(tolist 方法是实现这一目标的最快方法):

>>> dict(enumerate(zip(Q.argmax(axis=0).tolist(), 
...                    (Q.shape[0]-1-Q[::-1].argmax(axis=0)).tolist())))
{0: (0, 4), 1: (0, 1), 2: (0, 5), 3: (1, 6), 4: (2, 2), 5: (3, 6), 6: (2, 5)}

Q[::-1] 是反转数组,要获得“未反转”索引,我必须从 Q.shape[0]-1 中减去它们。

【讨论】:

    【解决方案2】:

    让我们从你的数组开始:

    >>> Q
    array([[1, 1, 1, 0, 0, 0, 0],
           [0, 1, 1, 1, 0, 0, 0],
           [1, 0, 0, 0, 1, 0, 1],
           [0, 0, 0, 1, 0, 1, 1],
           [1, 0, 1, 0, 0, 0, 0],
           [0, 0, 1, 0, 0, 0, 1],
           [0, 0, 0, 1, 0, 1, 0]])
    

    获取包含 1 的第一行的每一列的索引:

    >>> np.argmax(Q, axis=0) # Index of first appearance of 1
    array([0, 0, 0, 1, 2, 3, 2])
    

    获取包含 1 的最后一行的每一列的索引:

    >>> Q.shape[0] - np.argmax(Q[::-1, :], axis=0) - 1 # Index of last appearance of 1
    array([4, 1, 5, 6, 2, 6, 5])
    

    将它们组合成您喜欢的字典:

    >>> dict(enumerate(zip( np.argmax(Q, axis=0), Q.shape[0] - np.argmax(Q[::-1, :], axis=0) - 1)))
    {0: (0, 4), 1: (0, 1), 2: (0, 5), 3: (1, 6), 4: (2, 2), 5: (3, 6), 6: (2, 5)}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 2013-02-14
      • 2019-05-08
      • 2018-12-05
      • 2019-05-22
      • 2019-11-20
      • 1970-01-01
      相关资源
      最近更新 更多