Max*_*Max 3 wolfram-mathematica list
在Mathematica中,我有一个点坐标列表
size = 50;
points = Table[{RandomInteger[{0, size}], RandomInteger[{0, size}]}, {i, 1, n}];
Run Code Online (Sandbox Code Playgroud)
以及这些点所属的集群索引列表
clusterIndices = {1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1};
Run Code Online (Sandbox Code Playgroud)
根据clusterIndices值将点分成两个单独的列表的最简单方法是什么?
编辑:我提出的解决方案:
pointIndices =
Map[#[[2]] &,
GatherBy[MapIndexed[{#1, #2[[1]]} &, clusterIndices], First],
{2}];
pointsByCluster = Map[Part[points, #] &, pointIndices];
Run Code Online (Sandbox Code Playgroud)
有更好的方法吗?
正如@High Performance Mark和@Nicholas Wilson所说,我首先将两个列表组合在一起Transpose或通过Thread.在这种情况下,
In[1]:= Transpose[{clusterIndices, points}]==Thread[{clusterIndices, points}]
Out[1]:= True
Run Code Online (Sandbox Code Playgroud)
有一次,我看着哪个更快,我认为Thread速度稍快.但是,只有在使用很长的列表时才真正重要.
@High Performance Mark在建议方面提出了一个很好的观点Select.但是,它只允许您一次拉出一个群集.选择集群1的代码如下:
Select[Transpose[{clusterIndices, points}], #[[1]]==1& ][[All, All, 2]]
Run Code Online (Sandbox Code Playgroud)
由于您似乎想要生成所有集群,我建议您执行以下操作:
GatherBy[Transpose[{clusterIndices, points}], #[[1]]& ][[All, All, 2]]
Run Code Online (Sandbox Code Playgroud)
这是一个单线程的优点,唯一棘手的部分是选择正确Part的结果列表.确定需要多少All条款的诀窍就是要注意这一点
Transpose[{clusterIndices, points}][[All,2]]
Run Code Online (Sandbox Code Playgroud)
需要从转置列表中取回积分.但是,"聚集"列表有一个额外的级别,因此第二个级别All.
应该注意的是,第二个参数GatherBy是一个接受一个参数的函数,它可以与你想要使用的任何函数互换.因此,它非常有用.但是,如果您想将数据转换为收集数据,我会看看Reap并且Sow.
编辑: Reap并且Sow有些使用不足,相当强大.它们使用起来有些混乱,但我怀疑它GatherBy是在内部使用它们实现的.例如,
Reap[ Sow[#[[2]], #[[1]] ]& /@ Transpose[{clusterIndices, points}], _, #2& ]
Run Code Online (Sandbox Code Playgroud)
与我以前的代码做同样的事情,没有从点上剥离指数的麻烦.基本上,Sow标记每个点的索引,然后Reap收集所有标记(_对于第二个参数)并仅输出点.就个人而言,我使用它而不是GatherBy,我已将其编码为我加载的函数,如下所示:
SelectEquivalents[x_List,f_:Identity, g_:Identity, h_:(#2&)]:=
Reap[Sow[g[#],{f[#]}]&/@x, _, h][[2]];
Run Code Online (Sandbox Code Playgroud)
注意:此代码是5.x中帮助文件中的修改形式.但是,6.0和7.0帮助文件删除了许多有用的示例,这就是其中之一.
这是一个简洁的方法,使用SplitBy7.0版中的新功能,应该非常快:
SplitBy[Transpose[{points, clusterIndices}], Last][[All, All, 1]]
Run Code Online (Sandbox Code Playgroud)
如果您不使用7.0,则可以将其实现为:
Split[Transpose[{points, clusterIndices}], Last[#]==Last[#2]& ][[All, All, 1]]
Run Code Online (Sandbox Code Playgroud)
对不起,我没有看到你只想要两个组,我认为它们是聚类,而不是分裂.这是一些代码:
FindClusters[Thread[Rule[clusterIndices, points]]]
Run Code Online (Sandbox Code Playgroud)