Skip to main content

graphs and networks - Edge Labels with distance between vertices


I am trying to make traveling salesman type graph using the locations of NFL stadiums as the vertices. I need to get the EdgeLabels to appear was the distance between the vertices. I was able to slightly modify some code from


Building graph based on the cities connection?


but I am still unsure about how to incorporate the distances.


stateConnections = {{"TEN", "CAR"}, {"NYGJ", "PIT", "DET"}, {"SEA", 
"MIN" }, {"SFO", "SEA", "SDO"}, {"ARZ", "HOU"}, {"DAL",
"STL"}, {"PHI", "MIA", "KCY"}, {"OAK", "ARZ", "DEN"}, {"DEN",
"DAL"}, {"GBY", "CIN", "CHI"}, {"MIN", "MIA"}, {"NOR", "TEN",
"HOU"}, {"DET", "KCY"}, {"BUF", "CLE"}, {"CLE", "NWE"}, {"NWE",
"TBY"}, {"TBY", "STL"}, {"PIT", "BAL"}, {"JAC", "ATL"}, {"IND",

"BAL", "CHI"}, {"ATL", "CIN"}, {"JAC", "BUF"}, {"WAS", "CAR",
"JAC"}, {"SDO", "ARZ"}};


stateData = {"TEN,36.1665,-86.7713", "NYGJ,40.8122,-74.077", "PIT,40.4468,-80.0158", "CAR,35.2258,-80.8529", "BAL,39.278,-76.6228", "TBY,27.976,-82.5033",
"IND,39.7601,-86.1638", "MIN,44.9739,-93.2581",
"ARZ,33.5277,-112.263", "DAL,32.7478,-97.0928",
"ATL,33.7576,-84.401", "NYGJ,40.8122,-74.077",
"DEN,39.7439,-105.02", "MIA,25.9579,-80.2388",
"PHI,39.9008,-75.1675", "CHI,41.8623,-87.6167",

"NWE,42.0909,-71.2643", "WAS,38.9077,-76.8645",
"GBY,44.5013,-88.0622", "SDO,32.7831,-117.12",
"NOR,29.9509,-90.0814", "HOU,29.6848,-95.411",
"BUF,42.7737,-78.787", "SFO,37.7135,-122.386",
"JAC,30.3239,-81.6374", "CLE,41.506,-81.6996",
"OAK,37.7514,-122.201", "KCY,39.0489,-94.484",
"STL,38.633,-90.1885", "SEA,47.5952,-122.332",
"CIN,39.0954,-84.516", "DET,42.3402,-83.0458"};

stateAbbreviations = Union[Flatten[stateConnections]];

stateToNumber = MapThread[Rule, {stateAbbreviations, Range[Length[stateAbbreviations]]}];
numberToState = MapThread[ Rule, {Range[Length[stateAbbreviations]], stateAbbreviations}];
allConnections = Flatten[Function[e, Map[UndirectedEdge[First[e], #] &, Rest[e]]] /@ stateConnections];
connections = Union[Sort /@ allConnections];
stateCenters = First[StringSplit[#, ","]] -> ToExpression /@ RotateLeft@Rest[StringSplit[#, ","]] & /@ stateData;
stateCoords = (# & /@ stateAbbreviations) /. stateCenters;
temp = Graph[connections /. stateToNumber];
vertexCoordinates = stateCoords[[VertexList[temp]]];
g = Graph[connections /. stateToNumber, VertexCoordinates -> vertexCoordinates, VertexLabels -> numberToState, VertexShapeFunction -> "Circle", VertexSize -> 1, VertexLabelStyle -> Directive[Black, 7]];


Show[Graphics[{LightGray, CountryData["USA", "Polygon"]}], g, ImageSize -> 1000]

Answer



In Mathematica 10 it is easy to do with GeoDistance. Simply replace your g with the following lines


stateToLocation = 
Rule[First[#], ToExpression[Rest[#]]] & /@ (StringSplit[stateData,
","]);
edgeLabels =
Thread[Rule[
EdgeList[g], (EdgeList[g] /. numberToState /. stateToLocation) /.
UndirectedEdge -> GeoDistance]];

g = Graph[connections /. stateToNumber,
VertexCoordinates -> vertexCoordinates,
VertexLabels -> numberToState, VertexShapeFunction -> "Circle",
VertexSize -> 1, VertexLabelStyle -> Directive[Black, 7],
EdgeLabels -> edgeLabels];

Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...