如何沿行将相关的数组项合并为一个?

问题描述

在为指定每个原子的邻居进行一系列距离计算之后,我最终得到了以下邻居表(第一列是原子本身,第二列是它的邻居):

array([[ 0,1],[ 1,0],2],[ 2,3],[ 3,4],[ 4,5],...
       [48,47],[48,49],[49,48]])

例如,第 0 个原子只有一个邻居,由 1 索引(这是第 0 行的含义)。由 1 索引的第二个原子有两个由 02 索引的邻居,因为数字 1 在它们之间。就这样,最后,由于没有大于 49 的数字索引的原子,所以最后一个原子只有一个邻居,就像第 0 个原子一样,该邻居是由数字索引的原子48

我想要的是改变这个数组,使每一行只引用一个原子及其邻居,这样:

array([[ 0,1,2,3,47,48]])

其中第一列指的是原子本身,其余的列指的是它们的整个邻居。

因为数组将包含数十万个项目,并且会被调用数千次,所以我不想使用 python 循环。我正在寻找非常有效的方法来做到这一点。此外,第一个和最后一个原子的邻居不必是一个,其余原子的邻居不必是两个;一个原子的邻居数量可以改变。因此,一些索引方法可能无法解决这个问题,尽管一开始可能会奏效。

我想过数组操作方法,但我没能解决我的问题。如果您能指导我解决这个问题,我将不胜感激。谢谢。

解决方法

这看起来像一个 groupby 类型的操作,而 NumPy 并没有太多用于分组操作的内置功能,但是 Pandas 有。

以下是使用 Pandas groupby 高效执行此操作的示例:

import numpy as np
import pandas as pd

neighbors = np.array([[ 0,1],[ 1,0],2],[ 2,3],[ 3,4],[ 4,5],[48,47],49],[49,48]])

g = pd.Series(neighbors[:,1]).groupby(neighbors[:,0]).apply(list)
grouped = pd.DataFrame(g.to_list(),index=g.index).reset_index().to_numpy()

print(grouped)
# array([[ 0.,1.,nan],#        [ 1.,0.,2.],#        [ 2.,3.],#        [ 3.,2.,4.],#        [ 4.,3.,5.],#        [48.,47.,49.],#        [49.,48.,nan]])

请注意,numpy 不能在单个数组中具有异构行长度;在这里,pandas 使用 np.nan 作为缺失条目的填充值。