基于数组的另一列(Python)对一列中的最小-最大值进行聚集

基于数组的另一列(Python)对一列中的最小-最大值进行聚集,python,python-3.x,numpy,Python,Python 3.x,Numpy,如果这些值具有相同的索引,我将尝试连接它们。我正在使用矩形,因此我知道: 始终至少有两个相同的索引 如果有两个以上的索引,我只需要存储最大值和最小值 基本上 发件人: a = array([ [ 1, 5], [ 1, 7], [ 2, 8], [ 2, 10], [ 2, 22], [ 3, 55], [ 3, 77]]) 致: 我曾尝试将其转换为一个列表,并使用for循环遍历每个值,

如果这些值具有相同的索引,我将尝试连接它们。我正在使用矩形,因此我知道:

  • 始终至少有两个相同的索引
  • 如果有两个以上的索引,我只需要存储最大值和最小值
基本上

发件人:

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

我曾尝试将其转换为一个列表,并使用for循环遍历每个值,但这需要相当长的时间

我也尝试过对数组进行排序,
np.sort(a,axis=0)
并每隔一行进行一次排序,但由于索引可能不止两个,所以失败了

我对numpy还不熟悉,所以不知道还能尝试什么

任何建议都会有帮助,谢谢

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


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

使用
pandas

import pandas as pd
# create a dataframe with 2 columns corresponding to the columns of a
df = pd.DataFrame({ 'indices':a[:,0],'values':a[:,1]}) 
# compute min and max by indices
df2 = df.groupby('indices').agg({'values': ['min', 'max']}).reset_index()
# convert to numpy array
np.asarray(df2)
#array([[ 1,  5,  7],
#       [ 2,  8, 22],
#       [ 3, 55, 77]], dtype=int64)

使用
pandas

import pandas as pd
# create a dataframe with 2 columns corresponding to the columns of a
df = pd.DataFrame({ 'indices':a[:,0],'values':a[:,1]}) 
# compute min and max by indices
df2 = df.groupby('indices').agg({'values': ['min', 'max']}).reset_index()
# convert to numpy array
np.asarray(df2)
#array([[ 1,  5,  7],
#       [ 2,  8, 22],
#       [ 3, 55, 77]], dtype=int64)

用numpy做这件事的一种方式, 可以使用numpy.split根据第一个轴中的值将它们拆分为单独的数组。然后你可以找到最小值和最大值

有关拆分及其工作原理的详细信息, 你可以看看答案。我在这里不再重复同样的内容

ar = np.split(a, np.flatnonzero(a[1:,0] != a[:-1,0])+1,axis=0)
上面的行拆分并为轴0中的每个唯一值生成数组列表

上述行将产生如下输出:

[
array([[1, 5],
       [1, 7]]),
array([[ 2,  8],
       [ 2, 10],
       [ 2, 22]]), 
array([[ 3, 55],
       [ 3, 77]])
]
然后您可以迭代它们,以找到输出中所期望的列表的性质

final_list = []
for i in ar:
  final_list.append([i[1][0],np.min(i[:,1]),np.max(i[:,1])])
print(final_list)
上面的代码将生成如下输出

[[1, 5, 7], [2, 8, 22], [3, 55, 77]]

用numpy做这件事的一种方式, 可以使用numpy.split根据第一个轴中的值将它们拆分为单独的数组。然后你可以找到最小值和最大值

有关拆分及其工作原理的详细信息, 你可以看看答案。我在这里不再重复同样的内容

ar = np.split(a, np.flatnonzero(a[1:,0] != a[:-1,0])+1,axis=0)
上面的行拆分并为轴0中的每个唯一值生成数组列表

上述行将产生如下输出:

[
array([[1, 5],
       [1, 7]]),
array([[ 2,  8],
       [ 2, 10],
       [ 2, 22]]), 
array([[ 3, 55],
       [ 3, 77]])
]
然后您可以迭代它们,以找到输出中所期望的列表的性质

final_list = []
for i in ar:
  final_list.append([i[1][0],np.min(i[:,1]),np.max(i[:,1])])
print(final_list)
上面的代码将生成如下输出

[[1, 5, 7], [2, 8, 22], [3, 55, 77]]
这样做的一种方法(不是很好)是使用普通列表

# convert to list and sort if not already sorted
alist = a.tolist()
alist.sort()

# initial values for looping
currval = alist[0][0]
min     = alist[0][1]
max     = alist[0][1]

# new list to store results in
result = []

# loop through all rows of alist
for row in alist:
    if currval == row[0]: # still same index
        max = row[1]   # update max
    else:
        result.append([currval, min, max]) # save row
        currval = row[0] # update to next index
        min     = row[1]
        max     = row[1]

# save last row
result.append([currval, min, max]) # save row
currval = row[0] # update to next index
min     = row[1]
max     = row[1]

# convert output to nparray
b = np.array(result)
它利用Python对列表进行排序的
行为,通过将具有相同索引的列表分组并按递增顺序排列值,对列表进行良好排序。

一种方法是使用普通列表

# convert to list and sort if not already sorted
alist = a.tolist()
alist.sort()

# initial values for looping
currval = alist[0][0]
min     = alist[0][1]
max     = alist[0][1]

# new list to store results in
result = []

# loop through all rows of alist
for row in alist:
    if currval == row[0]: # still same index
        max = row[1]   # update max
    else:
        result.append([currval, min, max]) # save row
        currval = row[0] # update to next index
        min     = row[1]
        max     = row[1]

# save last row
result.append([currval, min, max]) # save row
currval = row[0] # update to next index
min     = row[1]
max     = row[1]

# convert output to nparray
b = np.array(result)
它利用Python对列表进行排序的
行为,通过将具有相同索引的列表分组并按递增顺序排列值,对列表进行良好排序。

方法#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]]
sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()
# 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()
如果每组都有很多条目,效果会更好


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

对于正整数,我们可以假设它们位于
2D
网格上,从而得到每行的线性索引等价物。因此,我们将跳过
lexsort
,然后像这样得到
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]]
sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()
# 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()
获取
sidx
后的其余代码在之前发布的两种方法中保持不变

备选方案2:使用
视图获取
sidx

我们可以使用
视图
获取
sidx
,然后再次跳过
lexsort
,如下所示-

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]]
sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()
# 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()
方法#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]]
sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()
# 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()
如果每组都有很多条目,效果会更好


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

对于正整数,我们可以假设它们位于
2D
网格上,从而得到每行的线性索引等价物。因此,我们将跳过
lexsort
,然后像这样得到
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]]
sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()
# 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()
获取
sidx
后的其余代码在之前发布的两种方法中保持不变

备选方案2:使用
视图获取
sidx

我们可以使用
视图
获取
sidx
,然后再次跳过
lexsort
,如下所示-

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]]
sidx = (a[:,0]*(a[:,1].max()+1) + a[:,1]).argsort()
# 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()

为了弄清楚你的意图,你能显示你的列表代码吗?@hpaulj我真的很抱歉,我打错了第二个数组,它现在已经修复了。我基本上是在尝试复制numpy中的一个字典,其中键是a[0],值是a[1:],只是为了弄清楚您的意图,您可以显示您的列表代码吗?@hpaulj非常抱歉,我键入了第二个数组,它现在已修复。我基本上是在尝试在numpy中复制一个字典,其中键是a[0],值是a[1:]谢谢您的快速响应,我正在尝试将我的项目包含在numpy中。有可能在numpy中复制相同的东西吗?如果没有,我会继续使用熊猫。@MohammadIslam我可以知道原因吗,为什么numpy的答案不是公认的答案,基于熊猫的答案在哪里?我只是想确定一下,如果我能纠正的话something@venkatakrishnan我很抱歉仓促接受了答案,我将仔细检查每个答案,看看它们的效果如何。我现在没时间,好吧。如果是这样的话,你可以接受任何答案。只是想确定有没有错误。学习愉快。感谢您的快速回复,我正在努力将我的项目包含在numpy中。有可能在numpy中复制相同的东西吗?如果没有,我会继续使用熊猫。@MohammadIslam我可以知道原因吗,为什么numpy的答案不是公认的答案,作为一名pa在哪里