我正在尝试将值具有相同的索引连接起来。我正在使用矩形,所以我知道:


总会有至少两个相同的索引。
如果有两个以上的索引,我只需要存储最大值和最小值。


基本上,

从:

a = array([
       [ 1,  5],
       [ 1,  7],
       [ 2,  8],
       [ 2, 10],
       [ 2, 22],
       [ 3, 55],
       [ 3, 77]])


至:

b = np.array([
       [ 1, 5, 7],
       [ 2, 8, 22], # [2,8,10,22] but the min is 8 and max is 22
       [ 3, 55, 77]])


我试图将其转换为列表,并使用for循环遍历每个值,但是这需要花费大量时间。

我还尝试对数组np.sort(a, axis=0)进行排序,并每隔一行走一次,但是由于可以有两个以上的索引,因此失败。

我是numpy的新手,所以不知道还能尝试什么。

任何和所有建议都会有所帮助,谢谢。

编辑:其行为类似于字典,其中键为a [0],值为a [1:]

如果有两个以上的值,则仅保留最小值和最大值。

最佳答案

方法1

向量NumPy的方式是-

def agg_minmax(a):
    sidx = np.lexsort(a[:,::-1].T)
    b = a[sidx]
    m = np.r_[True,b[:-1,0]!=b[1:,0],True]
    return np.c_[b[m[:-1],:2], b[m[1:],1]]


样品运行-

# Generic case with input not-necessarily sorted by first col
In [35]: a
Out[35]:
array([[ 3, 77],
       [ 2,  8],
       [ 1,  7],
       [ 2, 10],
       [ 1,  5],
       [ 3, 55],
       [ 2, 22]])

In [36]: agg_minmax(a)
Out[36]:
array([[ 1,  5,  7],
       [ 2,  8, 22],
       [ 3, 55, 77]])


方法#2

我们可以改进内存以按sidx仅对第一行进行排序,如下所示-

def agg_minmax_v2(a):
    sidx = np.lexsort(a[:,::-1].T)
    b = a[sidx,0]
    m = np.r_[True,b[:-1]!=b[1:],True]
    return np.c_[a[sidx[m[:-1]]],a[sidx[m[1:]],1]]


每个组有很多条目可能会更好。



备选方案1:使用线性索引映射获取sidx

对于正整数值,我们可以假定它们在2D网格上,因此可以得到每行的线性索引等效项。因此,我们将像这样跳过lexsort并获得sidx-

sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()


在两个较早发布的方法中,获取sidx后的其余代码保持不变。

备选方案2:使用sidx获取views

我们可以使用views来获取sidx,因此再次跳过lexsort,就像这样-

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

A = view1D(a)
sidx = A.argsort()

07-28 04:39