根据Mathematica中的另一个列表值拆分列表
在Mathematica中,我有一个点坐标列表
size = 50;
points = Table[{RandomInteger[{0, size}], RandomInteger[{0, size}]}, {i, 1, n}];
以及这些点属于的聚类索引列表
clusterIndices = {1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1};
根据clusterIndices值将点分成两个单独的列表最简单的方法是什么?
编辑:我想出了解决方案:
pointIndices =
Map[#[[2]] &,
GatherBy[MapIndexed[{#1, #2[[1]]} &, clusterIndices], First],
{2}];
pointsByCluster = Map[Part[points, #] &, pointIndices];
有没有更好的方法来做到这一点?
这个怎么样?
points[[
Flatten[Position[clusterIndices, #]]
]] & /@
Union[clusterIndices]
正如@High Performance Mark和@Nicholas Wilson所说的那样,我会先通过Transpose
或Thread
将两个列表结合在一起。 在这种情况下,
In[1]:= Transpose[{clusterIndices, points}]==Thread[{clusterIndices, points}]
Out[1]:= True
有一次,我看着哪一个更快,我认为Thread
稍快。 但是,当你使用很长的列表时,它才是真正重要的。
@High Performance Mark在推荐Select
很有用。 但是,它只允许您一次抽出一个群集。 选择群集1的代码如下所示:
Select[Transpose[{clusterIndices, points}], #[[1]]==1& ][[All, All, 2]]
由于您似乎想要生成所有群集,因此我建议您执行以下操作:
GatherBy[Transpose[{clusterIndices, points}], #[[1]]& ][[All, All, 2]]
其优点是作为一个班轮,唯一棘手的部分是选择正确的Part
结果列表。 在确定有多少诀窍All
条款是必要的是要注意,
Transpose[{clusterIndices, points}][[All,2]]
需要将点移出转置列表。 但是,“聚集”名单有一个额外的水平,因此第二个All
。
应该注意的是, GatherBy
中的第二个参数是一个接受一个参数的函数,它可以与您希望使用的任何函数互换。 因此,这非常有用。 但是,如果您希望在收集数据时转换数据,那么我会考虑Reap
和Sow
。
编辑: Reap
和Sow
有些在使用,并且相当强大。 他们使用起来有些困惑,但我怀疑GatherBy
是在内部使用它们实现的。 例如,
Reap[ Sow[#[[2]], #[[1]] ]& /@ Transpose[{clusterIndices, points}], _, #2& ]
和我之前的代码一样,没有从点上剥离索引的麻烦。 基本上, Sow
每个点标记其索引,然后Reap收集所有标记( _
用于第二个参数)并仅输出点。 就我个人而言,我使用这个而不是GatherBy,并且将它编码成我加载的函数,如下所示:
SelectEquivalents[x_List,f_:Identity, g_:Identity, h_:(#2&)]:=
Reap[Sow[g[#],{f[#]}]&/@x, _, h][[2]];
注意:此代码是5.x中帮助文件中的修改形式。 但是,6.0和7.0帮助文件删除了很多有用的例子,这是其中之一。
这里有一个简洁的方法来使用版本7.0中新的SplitBy
函数来实现这一点,该函数应该非常快:
SplitBy[Transpose[{points, clusterIndices}], Last][[All, All, 1]]
如果你不使用7.0,你可以这样实现:
Split[Transpose[{points, clusterIndices}], Last[#]==Last[#2]& ][[All, All, 1]]
更新
对不起,我没有看到你只想要两个组,我认为这是聚类,而不是分裂。 这里有一些代码:
FindClusters[Thread[Rule[clusterIndices, points]]]
链接地址: http://www.djcxy.com/p/35497.html
上一篇: Splitting a list based on another list values in Mathematica