# How to position vertices according to clustering coefficient in a nice way?

I have a graph and I want to rank each vertex according to its local clustering coefficient. I have done the following:

g = RandomGraph[BernoulliGraphDistribution[30, 0.25]];
Graph[g, VertexCoordinates -> Transpose[{RandomReal[1,
VertexCount[g]],N[LocalClusteringCoefficient[g]]}]]


The y coordinate of each vertex is the local clustering coefficient, but I don't have a good way to choose the x coordinate so I use a random number. This creates (unsurprisingly) a cluttered ugly graph.

Is there any build-in way to have such a layout that is less ugly?

• Can you rephrase the title? It's hardly understandable. As for the question in the body: I doubt that there is a good way to achieve this. Have you seen any plots which do the same things and look nice? – Szabolcs Jul 14 '19 at 15:22
• @Szabolcs I would gladly rephrase the title, but I'm not sure how to make it clearer. Do you have any suggestions? – tst Jul 14 '19 at 15:39
• Do you just mean "How to position vertices according to clustering coefficient in a nice way?" – user484 Jul 15 '19 at 12:04
• I think it's just a typo (what Rahul said). Do you have any reason to believe that a nice layout is possible this way? My guess is that in general it isn't. – Szabolcs Jul 15 '19 at 15:14

SeedRandom
g = RandomGraph[BernoulliGraphDistribution[30, 0.25]] "MultipartiteEmbedding"

You can sort and split the LocalClusteringCoefficient[g] and use the part lengths as the suboption value for "VertexPartition" in GraphEmbedding[g, {"MultipartiteEmbedding", "VertexPartition" -> vertexpartition}]. Replace the first coordinates with local clustering coefficients and normalize the second coordinates to get a list of VertexCoordinates where the horizontal axis values are local clustering coefficients:

v = SortBy[VertexList[g], LocalClusteringCoefficient[g, #] &];
lcc = Sort @ LocalClusteringCoefficient[g];
lengths = Length /@ Split[lcc];

ge = GraphEmbedding[g, {"MultipartiteEmbedding", "VertexPartition" -> lengths}];

ge[[All, 2]] = 2 ge[[All, 2]] / VertexCount[g];
ge[[All, 1]] = LocalClusteringCoefficient[g, #] & /@ v;
ge = Reverse /@ ge;

Graph[v, EdgeList[g], VertexCoordinates -> ge,
EdgeShapeFunction -> "CurvedArc", ImageSize -> Medium] If you care only about the ordering of property values, you can have a less less cluttered picture

ge = Reverse /@ GraphEmbedding[g,
{"MultipartiteEmbedding", "VertexPartition" -> lengths}];

Graph[v, EdgeList[g], VertexCoordinates -> ge,
EdgeShapeFunction -> "CurvedEdge",
VertexLabels -> Placed["Name", Center], VertexStyle -> White,
VertexSize -> .6, ImageSize -> Medium] GraphComputationGraphPropertyChart

An alternative approach is to use GraphComputationGraphPropertyChart to get a nice visualization of vertex properties in a PieChart with sector sizes proportional to the property values:

gpc = GraphComputationGraphPropertyChart[Graph[v, EdgeList[g]],
Automatic -> lcc /. 0 -> 10^-5,
ChartStyle -> "Rainbow", ImageSize -> Large] Click on a vertex to highlight the edges incident to that vertex: Highlight edges incident to selected vertices (using a modified version of explode from this answer by Simon Woods):

highlight[v_][chart_, i : {__}] := ReplacePart[chart,
Position[chart, False][[Flatten[Position[v, #] & /@ i]]] -> True]

highlight[v][gpc, {6, 9}] Update: GraphPlot + VertexCoordinateRules

Before version 12 updates, VertexCoordinateRules option of GraphPlot had the desired feature: So, if you have access to a version prior to v12, you can do

vcrules = Thread[v -> lcc] /. Rule[a_, b_] :> Rule[a, {Automatic, b}]
vcoords = GraphPlot[Rule @@@ EdgeList[g], VertexLabeling -> False,
VertexCoordinateRules -> vcrules][[1, 1, 1]];

Show[Graph[v, EdgeList[g], VertexCoordinates -> vcoords,
EdgeShapeFunction -> "CurvedArc",
VertexLabels -> Placed["Name", Center], VertexStyle -> White,
VertexSize -> .9, ImageSize -> Large], Frame -> True,
GridLines -> {None, DeleteDuplicates@lcc},
FrameTicks -> {N[Union[#, SameTest -> (Abs[#2 - #] <= .05 &)] & /@ {lcc,
lcc}], {Automatic, Automatic}}] Note: GridLines and FrameTicks added to show that vertical coordinates are as specified.

It is not the answer to the exact question I asked, because it is not a built-in method, but I think it works pretty well.

Initially I asked mathematica to choose the x coordinates so that it minimizes the total edge lengths. Unsurprisingly it positioned all vertices on the same line.

So, I changed the objective function by adding the sum of the inverse distance between any two vertices and the result is not bad at all.

g = RandomGraph[BernoulliGraphDistribution[30, 0.25]]
IM = IncidenceMatrix[gg];
CC = N[LocalClusteringCoefficient[g]];
coords = Transpose[{Table[x[i], {i, 30}], CC}];
eLenght =
Sum[e[]^2 + e[]^2, {e,
Transpose[{Table[x[i], {i, 30}].IM, CC.IM}]}];
invdists =
Total[1/DeleteCases[
Flatten[Table[(p[] - q[])^2 + (p[] - q[])^2, {p,
coords}, {q, coords}]], 0.]];
minsol = Minimize[eLenght + 1/10000 invdists,
Table[x[i], {i, 30}]][];
Graph[g, VertexCoordinates -> coords /. minsol]
`

This turns a graph like this: to a graph like this: I suspect that the minimum is not unique, but I am content with the result for now.