How to load edges and nodes into a matlab network

Is it possible to load edges and nodes into matlab for network/graph analysis (I want to model node centrality on a real network)?
I have a point file (file 1) With XYZ coordinates and unique name for nodes.
I have an edge file with two columns that describe the start and end nodes in file 1. (this was a polyline export from ArcGIS).
Any resources you could point me to would be greatly appreciated! I'm trying to model river network centrality...
This may not be possible... just was curious as I'm a beginner.

 Respuesta aceptada

Ameer Hamza
Ameer Hamza el 7 de Oct. de 2020
Editada: Ameer Hamza el 7 de Oct. de 2020

2 votos

Yes, MATLAB has several functions to create and analyze graphs. Read here: https://www.mathworks.com/help/matlab/graph-and-network-algorithms.html

Más respuestas (1)

William Wadsworth
William Wadsworth el 7 de Oct. de 2020

0 votos

Hi Ameer,
Thanks for these, i've taken a look. What functions I would need to make the graph object? I essentially want to recreate the Minnesota example here but with my own data. https://www.mathworks.com/help/matlab/ref/graph.centrality.html
I have a table of edges and a table of nodes I will need to import...
Thanks again, any advice would be greatly appreciated!

18 comentarios

Steven Lord
Steven Lord el 7 de Oct. de 2020
You would need to create a graph or digraph using the functions listed in the Construction section on this documentation page. Since you have coordinate data you're probably going to want to store those as "Other Attributes" in the Nodes table of the graph or digraph as per the fourth item in the Topics section on that page. To use that coordinate data when plotting, see the "Custom Graph Node Coordinates" example on the documentation page for the plot function for network objects. The plot function is listed in the Visualization section on that documentation page to which I linked in the first sentence.
Hi Steven, thanks for this. I feel like I'm on my way to figuring this out... Is there a way to add all the nodes in the table to the graph? I'm looking at those documents and it seems that they add specific nodes (whereas, I have 10000 points). If so, is there a similar function for the edges?... After that i think the graph network is constructed...
This is what i've been trying to do...
G = graph;
Node.Table=table(X,Y,Z,N);
G = addnode(G, Node.Table);
Ameer Hamza
Ameer Hamza el 8 de Oct. de 2020
Can you show how the data for nodes and edges is available? Is it a text file? Can you share a sample?
Absolutely! The Sharenodes file is the file I want to add as nodes to the graph. It is a large file, so I've only shared 3 nodes as a test.
The share nodes is a text file with 5 columns, the first two are arcgis output, then easting, northing and a unique nodename number.
The Edge list is just a 2- column adjacency matrix specifying which nodes are to be connected.
Thank you!!!
See this example
nodes_info = readtable('ShareNodes.txt');
edges_info = readtable('ShareEdges.txt');
G = graph();
G = G.addnode(string(nodes_info.Nodename));
G = G.addedge(string(edges_info.NodenameFR), string(edges_info.NodenameTO));
plot(G);
Thanks Ameer, this is getting better. When trying to plot the nodes in geographic coordinates I am trying to use the bolded line below. However, I get the error:
"Error using matlab.graphics.chart.primitive.GraphPlot. Expected XData to be one of these types: double, single, uint8, uint16, uint32, uint64, int8, int16, int32, int64. Instead its type was table."
Since it is a table what should i be using instead of below to identify x y z coordinates in table?
nodes_info = readtable('RiverNetworkNodesTrim.txt');
edges_info = readtable('RiverNetworkEdgeMatrix.txt');
x = nodes_info(:,4);
y = nodes_info(:,5);
z = nodes_info (:,6);
G = graph();
G = G.addnode(string(nodes_info.Nodename));
G = G.addedge(string(edges_info.NodenameFR), string(edges_info.NodenameTO));
plot(G,'XData',x,'YData',y,'ZData',z)
table elements are accessed using brace indexing
plot(G, 'XData', nodes_info{:,4}, 'YData', nodes_info{:,5}, 'ZData', nodes_info{:,6});
or using column name
plot(G, 'XData', nodes_info.Easting, 'YData', nodes_info.Northing, 'ZData', nodes_info.RASTERVALU);
Hi Ameer,
This is fantastic! Thank you for your help.
Theoretical question, If I wanted to add a distance matrix between the points, should I do that or does this plot with these plotted points contain this information?
Also I get an error that says my ZData needs to be finite. If I remove the Zdata variable this isn't an issue, but if I wanted to keep it in... does this error message signal a problem within the data file itself (i.e. a negative number somewhere)?
Distance as the crow flies between your points or as the ant crawls along the edges between your points? For the former compute the norm of the vector formed by subtracting coordinates of the points. For the latter, you probably want to use the distances function on your graph.
For the error about ZData not being finite, that means your data contains Inf or NaN values. You can see which ones aren't using isfinite then look back at the corresponding rows of your RiverNetworkNodesTrim.txt file.
>> x = [1 2 Inf 4 NaN 6 7];
>> F = isfinite(x)
F =
1×7 logical array
1 1 0 1 0 1 1
>> x(F)
ans =
1 2 4 6 7
>> x(~F)
ans =
Inf NaN
As Steven mentioned, there is likely a NaN of Inf in the Z column.
Also, the weights are not automatically calculated by graphs when plotted. You need to specify the distances between nodes yourself. The following code shows a simple approach for calculating the distance values. I believe more efficient approaches should be possible.
nodes_info = readtable('ShareNodes.txt');
edges_info = readtable('ShareEdges.txt');
distances = zeros(size(edges_info,1),1);
for i = 1:numel(distances)
src = edges_info{i,1};
dst = edges_info{i,2};
idx_src = src == nodes_info{:,7};
idx_dst = dst == nodes_info{:,7};
src_pos = nodes_info{idx_src, 4:6};
dst_pos = nodes_info{idx_dst, 4:6};
distances(i) = norm(src_pos-dst_pos);
end
G = graph();
G = G.addnode(string(nodes_info.Nodename));
G = G.addedge(string(edges_info.NodenameFR), string(edges_info.NodenameTO), distances);
plot(G, ...
'XData', nodes_info{:,4}, ...
'YData', nodes_info{:,5}, ...
'ZData', nodes_info{:,6}, ...
'EdgeLabel', G.Edges.Weight);
Here is another approach for calculating the distances. Not sure which one is more efficient for a large dataset. Maybe you can try and share the timing results.
nodes_info = readtable('ShareNodes.txt');
edges_info = readtable('ShareEdges.txt');
G = graph();
G = G.addnode(string(nodes_info.Nodename));
G = G.addedge(string(edges_info.NodenameFR), string(edges_info.NodenameTO), zeros(size(edges_info,1),1));
G.Nodes.X = nodes_info.Easting;
G.Nodes.Y = nodes_info.Northing;
G.Nodes.Z = nodes_info.RASTERVALU;
for i = 1:G.numedges
idx = G.findnode(G.Edges.EndNodes(i,:));
src_pos = G.Nodes{idx(1), 2:3};
dst_pos = G.Nodes{idx(2), 2:3};
G.Edges.Weight(i) = norm(src_pos-dst_pos);
end
plot(G, ...
'XData', nodes_info{:,4}, ...
'YData', nodes_info{:,5}, ...
'ZData', nodes_info{:,6}, ...
'EdgeLabel', G.Edges.Weight);
Hi Ameer, I had been following Steven's tips and came up with this code because I want to calculate euclidean distance as edge weight (since the ultimate goal of this will be to do centrality analysis). Does the following make sense? If not which piece of your code should I use? :)
%% Load Data, Construct Graph Object of Nodes and Edges, plot regular figure
figure('Name','River Network')
nodes_info = readtable('RiverNetworkNodesTrim.txt');
edges_info = readtable('RiverNetworkEdgeMatrix.txt');
G = graph();
G = G.addnode(string(nodes_info.Nodename));
G = G.addedge(string(edges_info.NodenameFR), string(edges_info.NodenameTO));
[s,t] = findedge(G); %calls the edges.
xy = [nodes_info.Northing nodes_info.Easting] %creates a variable for the distance calculation.
G.Edges.Weight = hypot(xy(s,1)-xy(t,1), xy(s,2)-xy(t,2)); %calculates euclidean distance between the xy coordinates of each.
p=plot(G, 'XData', nodes_info.Northing, 'YData', nodes_info.Easting, 'MarkerSize',5); % add Z back in once I remove zeroes...
title('River Network')
Ameer Hamza
Ameer Hamza el 8 de Oct. de 2020
Yes, this code also make sense. The distance calculations are correct.
Hi Ameer and Steven,
Last question, then I'm going to close this thread. Thank you too both for all your help!!
How would I modify this specific line of code to calculate XYZ euclidiean distance? I would like to get distance "as the ant crawls" as Steven said...
xy = [nodes_info.Northing nodes_info.Easting]
G.Edges.Weight = hypot(xy(s,1)-xy(t,1), xy(s,2)-xy(t,2));
Thanks again!!
Ameer Hamza
Ameer Hamza el 9 de Oct. de 2020
I guess there is some confusion here. Your current code calculates the distance as an ant crawls along the edges. The other case ("as the crow flies") does not require you to develop a graph. You just take two nodes and use their coordinates to calculate the distance. In that case, you don't care if there is an edge between these two nodes, just like a crow, which can fly in a straight line between any two points, whereas an ant can only move along edges to reach the destination. If there is no direct path, the ant needs to go through intermediate nodes.
That makes sense! Thank you! So I wouldn't change it to include elevation or do something like this?
xyz = [nodes_info.Northing nodes_info.Easting nodes_info.RASTERVALUE] %creates a variable for the distance calculation.
G.Edges.Weight = hypot(xyz(s,1)-xyz(t,1), xyz(s,2)-xyz(t,2));
You can still use the z value in the calculation of distance by directly using vecnorm() [a general form of hypot()]
G.Edges.Weight = vecnorm(xyz(s,:)-xyz(t,:),2,2);
Thank you!!

Iniciar sesión para comentar.

Categorías

Más información sobre Graph and Network Algorithms en Centro de ayuda y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by