tom*_*omd 5 wolfram-mathematica
是否有任何方法可以从GraphPlot生成的图形的(FullForm或InputForm)中抽象出GraphPlot应用于VertexCoordinate规则的顶点顺序?我不想使用GraphUtilities函数VertexList.我也知道GraphCoordinates,但这两个函数都适用于图形,而不是GraphPlot的图形输出.
例如,
gr1 = {1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 1};
gp1 = GraphPlot[gr1, Method -> "CircularEmbedding",
VertexLabeling -> True];
Last@(gp1 /. Graphics[Annotation[x___], ___] :> {x})
Run Code Online (Sandbox Code Playgroud)
给出以下六个坐标对的列表:
VertexCoordinateRules - > {{2.,0.866025},{1.5,1.723205},{0.5,1.723205},{0.,0.866025},{0.5,1.3349*10 ^ -10},{1.5,0.}}
我如何知道哪个规则适用于哪个顶点,我可以确定这与VertexList [gr1]给出的规则相同吗?
例如
Needs["GraphUtilities`"];
gr2 = SparseArray@
Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]];
VertexList[gr2]
Run Code Online (Sandbox Code Playgroud)
给出{1,2,3,4,5}
但......
gp2 = GraphPlot[gr2, VertexLabeling -> True,
VertexCoordinateRules ->
Thread[VertexList[gr1] ->
Last@(gp1 /. Graphics[Annotation[x___], ___] :> {x})[[2]]]];
Last@(gp2 /. Graphics[Annotation[x___], ___] :> {x})
Run Code Online (Sandbox Code Playgroud)
给出SIX坐标集:
VertexCoordinateRules - > {{2.,0.866025},{1.5,1.723205},{0.5,1.723205},{0.,0.866025},{0.5,1.3349*10 ^ -10},{1.5,0.}}
例如,如何为gr2的VertexCoordinateRules抽象正确的VertexList?
(我知道我可以通过生成gr2之后的VertexList进行更正,例如)
VertexList@
SparseArray[
Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]], {6, 6}]
Run Code Online (Sandbox Code Playgroud)
{1,2,3,4,5,6}
但我需要的信息似乎出现在GraphPlot图形中:我如何获得它?
(我将图形转换为邻接矩阵的原因是,正如Wolfram的Carl Woll所指出的那样,它允许我包含一个'孤儿'节点,如gp2中所示)

使用顶点标注,一种方法是获取标签的坐标.请注意,GraphPlot的输出位于GraphicsComplex中,其中坐标别名的坐标作为第一个标签,您可以将其作为
points = Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // First
Run Code Online (Sandbox Code Playgroud)
看着FullForm你会看到标签在文本对象中,将它们提取为
labels = Cases[gp1, Text[___], Infinity]
Run Code Online (Sandbox Code Playgroud)
实际的标签似乎是两层深,所以你得到
actualLabels = labels[[All, 1, 1]];
Run Code Online (Sandbox Code Playgroud)
坐标别名是第二个参数,因此您可以将它们作为
coordAliases = labels[[All, 2]]
Run Code Online (Sandbox Code Playgroud)
实际坐标在GraphicsComplex中指定,因此我们将它们作为
actualCoords = points[[coordAliases]]
Run Code Online (Sandbox Code Playgroud)
坐标列表和标签列表之间有1-1对应关系,因此您可以使用Thread将它们作为"标签" - >坐标对的列表返回.
这是一个功能,这一切都在一起
getLabelCoordinateMap[gp1_] :=
Module[{points, labels, actualLabels, coordAliases, actualCoords},
points =
Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] //
First;
labels = Cases[gp1, Text[___], Infinity];
actualLabels = labels[[All, 1, 1]];
coordAliases = labels[[All, 2]];
actualCoords = points[[coordAliases]];
Thread[actualLabels -> actualCoords]
];
getLabelCoordinateMap[gp1]
Run Code Online (Sandbox Code Playgroud)
并非这仅适用于标记的GraphPlot.对于没有标签的人,您可以尝试从其他图形对象中提取,但是根据您从中提取映射的对象,您可能得到不同的结果,因为似乎有一个错误,有时会将线端点和顶点标签分配给不同的顶点.我已经报道了.解决这个问题的方法是始终使用VertexCoordinateList的显式顶点 - >坐标规范,或者始终使用"邻接矩阵"表示.这是一个差异的例子
graphName = {"Grid", {3, 3}};
gp1 = GraphPlot[Rule @@@ GraphData[graphName, "EdgeIndices"],
VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"],
VertexLabeling -> True]
gp2 = GraphPlot[GraphData[graphName, "AdjacencyMatrix"],
VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"],
VertexLabeling -> True]
Run Code Online (Sandbox Code Playgroud)
顺便说一句,顺便说一句,这里是我用于在邻接矩阵和边缘规则表示之间进行转换的效用函数
edges2mat[edges_] := Module[{a, nodes, mat, n},
(* custom flatten to allow edges be lists *)
nodes = Sequence @@@ edges // Union // Sort;
nodeMap = (# -> (Position[nodes, #] // Flatten // First)) & /@
nodes;
n = Length[nodes];
mat = (({#1, #2} -> 1) & @@@ (edges /. nodeMap)) //
SparseArray[#, {n, n}] &
];
mat2edges[mat_List] := Rule @@@ Position[mat, 1];
mat2edges[mat_SparseArray] :=
Rule @@@ (ArrayRules[mat][[All, 1]] // Most)
Run Code Online (Sandbox Code Playgroud)
小智 1
p2 = Normal@gp1 // Cases[#, Line[points__] :> points, Infinity] &;
p3 = Flatten[p2, 1];
ListLinePlot[p3[[All, 1 ;; 2]]]
Run Code Online (Sandbox Code Playgroud)
V12.0.0