NETWORK Procedure

Example 2.20 Node Embeddings for European Roads Data

This example uses a European roads data set that is maintained by the Neo4j graph embeddings tutorial (Needham 2020). The graph includes 1,250 roadway connections among 894 cities and towns. You can compute node embeddings for these places by using vector node similarity. To simplify visualization, you can limit the data set to the seven most populous European countries: Spain, Great Britain, France, Turkey, Italy, Germany, and Greece. The graph is shown in Figure 247.

Figure 247: European Roads Graph

European Roads Graph


You can represent the graph by using the following links data table, mylib.LinkSetIn. The following statements create the data table mylib.Roads from a local copy of the raw European roads data:

filename in 'roads.csv';
data mylib.Roads;
   infile in missover firstobs = 2 DSD;
   length from to $40;
   input
      road_number $
      from_country $
      from $
      to_country $
      to $
      distance
      watercrossing $;
run;

The following statements construct the nodes and links data tables, mylib.Nodes and mylib.Links, from the raw roads data:

%let country_subset = ("E", "GB", "F", "TR", "I", "D", "GR");
data mylib.nodes;
   set mylib.Roads(
         rename=(from=node from_country=country)
      )
      mylib.Roads(
         rename=(to=node to_country=country)
      );
   by country node;
   if FIRST.node
      and country in &country_subset;
   if      country EQ 'D'  then color=1;
   else if country EQ 'E'  then color=2;
   else if country EQ 'F'  then color=3;
   else if country EQ 'GB' then color=4;
   else if country EQ 'GR' then color=5;
   else if country EQ 'I'  then color=6;
   else if country EQ 'TR' then color=7;
   keep node country color;
run;
data mylib.Links;
   set mylib.Roads;
   where from_country in &country_subset and to_country in &country_subset;
run;

The following statements use the EMBED=TRUE option to generate node embeddings for the European roads data:

proc network
   links    = mylib.Links
   nodes    = mylib.Nodes
   outNodes = mylib.OutNodesEmb;
   nodesVar
      vars  = (country color);
   nodeSimilarity
      jaccard        = false
      embed          = true
      nDimensions    = 300
      proximityOrder = first
      nSamples       = 10000000;
run;

The output data table mylib.OutNodesEmb contains the embedding vectors for each node. The first three components of five sample node embedding vectors are shown in Output 2.20.1.

Output 2.20.1: Embedding Vectors Output

nodevec_1vec_2vec_3
Alessandria-0.042850.0158410.048797
Belfast0.199210.012813-0.057647
Hamburg-0.020780.060347-0.045608
Milano-0.005850.0116050.018188
Rennes0.00620-0.062755-0.047990


For ease of visualization, it is common practice to collapse the multidimensional embeddings down to two dimensions. You can achieve this by using the TSNE procedure.

The following PROC TSNE statements produce a two-dimensional representation of the node embeddings:

proc tsne
   seed        = 1
   data        = mylib.OutNodesEmb
   nDimensions = 2
   perplexity  = 15
   maxIters    = 3000;
   input         vec_:;
   output
      out      = mylib.OutNodesTsne
      copyvars = (node country color);
run;

For validation, you can visualize the node embeddings. You can plot the two-dimensional embeddings representation, colored by country, by using the following PROC TEMPLATE and PROC SGRENDER statements:

proc template;
   define statgraph vectorPlot;
   begingraph;
      entrytitle "TSNE Embeddings Colored by Country: Vector";
      legendItem type=marker name="d" /
      markerattrs=(color=CX7FC97F symbol=circlefilled)
      label="Germany" ;
      legendItem type=marker name="e" /
      markerattrs=(color=CXBEAED4 symbol=circlefilled)
      label="Spain" ;
      legendItem type=marker name="f" /
      markerattrs=(color=CXFDC086 symbol=circlefilled)
      label="France" ;
      legendItem type=marker name="gb" /
      markerattrs=(color=CXFFFF99 symbol=circlefilled)
      label="Great Britain" ;
      legendItem type=marker name="gr" /
      markerattrs=(color=CX386CB0 symbol=circlefilled)
      label="Greece" ;
      legendItem type=marker name="i" /
      markerattrs=(color=CXF0027F symbol=circlefilled)
      label="Italy" ;
      legendItem type=marker name="tr" /
      markerattrs=(color=CXBF5B17 symbol=circlefilled)
      label="Turkey" ;
      layout overlay /
         yaxisopts=(labelFitPolicy=Split)
         y2axisopts=(labelFitPolicy=Split);
         ScatterPlot X=_DIM_1_ Y=_DIM_2_ /
            markerattrs=(symbol=circlefilled size=10)
            colormodel=(CX7FC97F CXBEAED4 CXFDC086 CXFFFF99 CX386CB0 CXF0027F CXBF5B17)
            colorresponse=color
            name="scatter";
         discretelegend "d" "e" "f" "gb" "gr" "i" "tr";
      endlayout;
   endgraph;
   end;
run;

proc sgrender data=mylib.OutNodesTsne template=vectorPlot; /* use GTL template */
run;

Output 2.20.2: TSNE Representation of Vector Node Embeddings

TSNE Representation of Vector Node Embeddings


In the plot shown in Output 2.20.2, note that the nodes representing places within the same country (color) appear to be clustered together in the embedded vector space.

The embeddings that are learned by using vector node similarity are functionally similar to the alternative techniques DeepWalk (Perozzi, Al-Rfou, and Skiena 2014; Perozzi 2014) and Node2Vec (Grover and Leskovec 2016; Grover 2016). Although these alternatives are not currently supported in PROC NETWORK, the results are provided here for comparison. The results that are obtained by DeepWalk for the same graph are shown in Output 2.20.3, and the results that are obtained by Node2Vec for the same graph are show in Output 2.20.4.

Output 2.20.3: TSNE Representation of DeepWalk Node Embeddings

TSNE Representation of DeepWalk Node Embeddings


Output 2.20.4: TSNE Representation of Node2Vec Node Embeddings

TSNE Representation of Node2Vec Node Embeddings


Last updated: August 07, 2026