Python/Numpy:按公共元素对数组行进行分组

Python/Numpy:按公共元素对数组行进行分组,python,algorithm,numpy,sorting,grouping,Python,Algorithm,Numpy,Sorting,Grouping,假设我有这样一个数组: [[1,2,3] [0,4,2] [4,2,5] [6,1,1] [1,3,5] [3,0,1] [0,4,2]] 我想通过让与其他行具有相同元素的任何行属于同一类别来对数组的行进行分类。通常,数组不仅可以由整数组成,还可以是任何浮点。这是一项要求,各要素必须在同一位置一致。对于上面的数组,类别将是 [[0], [1], [0], [2], [0], [2], [1]] 注意:每个类别中的每个成员都应与同一类别中的至少一个其他成员共享同一位置

假设我有这样一个数组:

[[1,2,3]
 [0,4,2]
 [4,2,5] 
 [6,1,1]
 [1,3,5]
 [3,0,1]
 [0,4,2]]
我想通过让与其他行具有相同元素的任何行属于同一类别来对数组的行进行分类。通常,数组不仅可以由整数组成,还可以是任何浮点。这是一项要求,各要素必须在同一位置一致。对于上面的数组,类别将是

[[0],
 [1],
 [0],
 [2],
 [0],
 [2],
 [1]]
注意:每个类别中的每个成员都应与同一类别中的至少一个其他成员共享同一位置的共同编号。并非同一类别中的所有成员对都需要在公共位置共享公共编号


你能想出一个可靠的方法来实现这一点吗?

这将为你提供常用的行对。其余部分取决于您对我的评论的回答,一旦我正确理解了问题,我将更新我的评论:

pairs = np.argwhere(((a[:,None]-a)==0).any(axis=2))
更新:根据类别的注释定义,这将返回类别:

b = np.arange(a.shape[0])
for pair in pairs:
  b[np.flatnonzero(b==b[pair[1]])] = b[pair[0]]
b = b - b.min()
通过在for循环之前从
中删除自边和重复边(每条边有两条),您可能可以更快地执行此操作

输出:

[0 2 0 1 0 1 2]
类别映射名称与所讨论的输出不同,但类别相同。如果希望以不同的方式命名,只需将代码的最后一行
b=b-b.min()
更改为所需的命名即可


另一种方法是使用edgelist
pairs
创建图形并提取连接的组件。

这不是一种可矢量化的操作。使用
networkit.components
。同一类别中的3行可以共享不同的位置公共性?或者每个类别中的每一对都应该有共性吗?(也就是说,及物性适用于一个类别的成员?)。虽然你的建议很好(我个人更喜欢),但如果你绝对肯定的话,请拒绝解决方案。事实上,组件也有矢量化解决方案。谢谢。@Ehsan类别中的每一对都应该在公共位置至少有一个公共元素。即以下各项属于同一类别:(0,42,7)、(0,61,31)、(13,61,11)、(13,59,11)。在这里,前两个在同一位置共享零,第二个和第三个在同一位置共享61,第三个和第四个在同一位置共享13和11。期待你的回答@MikkelRev您的陈述与您的示例相矛盾:类别中的每一对应该至少有一个公共元素,但
(0,42,7)
(13,59,11)
不共享公共元素。所以我猜你的意思是每个类别中的每个元素都应该与同一类别中的至少一个其他元素共享一个相同的数字,对吗?@MikkelRev numpy很强大。当然,另一种方法是使用edgelist
pairs
创建图形并提取连接的组件。不确定哪一个对您的输入大小更快。我怀疑有问题。我想它一定在倒数第二行。因为如果我尝试a=np.数组([[1,2,3,4],[5,6,7,8],[9,10,11,28],[13,14,15,8],[1,18,19,20],[21,22,23,24],[25,18,27,28]):很明显,行号0和4属于同一类别,因为它们在第一个位置共享一个1,但是代码打印出[1,0,3,0,3,2,3]。你能看到一个简单的解决办法吗?@MikkelRev-aah,似乎有<代码>成对可以。我会修好的。“谢谢你抓住了它。”米克尔雷夫我把它修好了。它可能不是最快的。这可能是一种更快的方法。但它现在起作用了。若你们需要更快的方法,请告诉我,我可以试着推它。