如果它们具有相同的索引,我试图将它们连接起来。我正在处理矩形,所以我知道:
基本上
发件人:
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:]
如果有两个以上的值,我只会保留最小值和最大值。
答案 0 :(得分:2)
使用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)
答案 1 :(得分:2)
使用numpy的方法, 您可以使用numpy.split根据第一个轴上的值将它们拆分为独立的数组。然后您可以找到最小和最大。
有关拆分及其工作方式的更多信息, 您可以查看答案here。我在这里不再重复。
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]]
答案 2 :(得分: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()
答案 3 :(得分:0)
一种这样做的方法(不太好)是使用普通列表。
# 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在列表上的sort
行为,通过对具有相同索引的值进行分组并将值按升序排列,从而很好地对列表进行排序。