NETWORK Procedure
Example 2.18 A Node Similarity Recipe Recommendation Engine
When recommending products to consumers, retailers often build models that are based on known relationships between consumers and products, such as purchase history or online reviews. These models are known as recommendation engines. This example builds a model that recommends recipes that are most similar and most dissimilar from each other, based on the similarity of their ingredient lists. The data set consists of six sauce recipes, each consisting of some subset of ingredients. The inclusion of ingredients in recipes is organized into a bipartite network G, shown in Figure 245.
Figure 245: Recipe-Ingredient Network G

The links of G are constructed from raw data that are specified in adjacency list format in the DATA step:
data mylib.LinkSetRecipesIn;
infile datalines dsd flowover;
length Recipe $20. Ingredient1-Ingredient13 $20.;
input Recipe $ Ingredient1-Ingredient13 $;
array ingredient Ingredient1 -- Ingredient13;
from = Recipe;
do over ingredient;
if missing(ingredient) then leave;
to = Ingredient;
output;
end;
keep from to;
datalines;
Spag Sauce, Tomato,Garlic,Salt,Onion,TomatoPaste,OliveOil
Oregano,Parsley, , , , ,
Spag Meat Sauce, Tomato,Garlic,Salt,Onion,TomatoPaste,OliveOil
Celery,GreenPepper,BayLeaf,GroundBeef,Carrot
PorkSausage,RedPepper
Eggplant Relish, Garlic,Salt,Onion,TomatoPaste,OliveOil,Eggplant
GreenOlives,Capers,Sugar, , , ,
Creole Sauce, Tomato,Salt,Onion,TomatoPaste,OliveOil,Celery
Broth,GreenPepper,BlackPepper,Paprika,Thyme
WorcestershireSauce,
Salsa, Tomato,Garlic,Salt,Onion,Cilantro,Tomatillo
JalapenoPepper,Lime, , , , ,
Enchilada Sauce, Tomato,Broth,Cumin,Flour,BrownSugar,ChiliPowder
CayennePepper,Oil, , , , ,
;
In this example, the cosine node similarity scores between pairs of recipes are of interest.
The following DATA step defines the subset of nodes that represent the six recipes:
data mylib.NodesSubsetRecipesIn;
infile datalines dsd;
length node $20.;
source = 1;
sink = 1;
input node;
datalines;
Spag Sauce
Spag Meat Sauce
Eggplant Relish
Creole Sauce
Salsa
Enchilada Sauce
;
The following statements produce the output data table mylib.NodeSim, which contains the cosine similarity scores between the nodes in the input subset; higher similarity scores indicate greater overlap of the recipes’ ingredient lists.
proc network
links = mylib.LinkSetRecipesIn
nodesSubset = mylib.NodesSubsetRecipesIn;
nodeSimilarity
jaccard = false
cosine = true
outSimilarity = mylib.SimilarityRecipesOut;
run;
The output data table mylib.SimilarityRecipesOut contains the cosine similarity score of each recipe node pair, as shown in Output 2.18.1.
Output 2.18.1: Recipe Cosine Similarity Output
| source | sink | cosine |
|---|---|---|
| Creole Sauce | Creole Sauce | 1.00000 |
| Creole Sauce | Spag Meat Sauce | 0.56045 |
| Creole Sauce | Spag Sauce | 0.51031 |
| Creole Sauce | Eggplant Relish | 0.38490 |
| Creole Sauce | Salsa | 0.30619 |
| Creole Sauce | Enchilada Sauce | 0.20412 |
| Eggplant Relish | Eggplant Relish | 1.00000 |
| Eggplant Relish | Spag Sauce | 0.58926 |
| Eggplant Relish | Spag Meat Sauce | 0.46225 |
| Eggplant Relish | Creole Sauce | 0.38490 |
| Eggplant Relish | Salsa | 0.35355 |
| Eggplant Relish | Enchilada Sauce | 0.00000 |
| Enchilada Sauce | Enchilada Sauce | 1.00000 |
| Enchilada Sauce | Creole Sauce | 0.20412 |
| Enchilada Sauce | Spag Sauce | 0.12500 |
| Enchilada Sauce | Salsa | 0.12500 |
| Enchilada Sauce | Spag Meat Sauce | 0.09806 |
| Enchilada Sauce | Eggplant Relish | 0.00000 |
| Salsa | Salsa | 1.00000 |
| Salsa | Spag Sauce | 0.50000 |
| Salsa | Spag Meat Sauce | 0.39223 |
| Salsa | Eggplant Relish | 0.35355 |
| Salsa | Creole Sauce | 0.30619 |
| Salsa | Enchilada Sauce | 0.12500 |
| Spag Meat Sauce | Spag Meat Sauce | 1.00000 |
| Spag Meat Sauce | Spag Sauce | 0.58835 |
| Spag Meat Sauce | Creole Sauce | 0.56045 |
| Spag Meat Sauce | Eggplant Relish | 0.46225 |
| Spag Meat Sauce | Salsa | 0.39223 |
| Spag Meat Sauce | Enchilada Sauce | 0.09806 |
| Spag Sauce | Spag Sauce | 1.00000 |
| Spag Sauce | Eggplant Relish | 0.58926 |
| Spag Sauce | Spag Meat Sauce | 0.58835 |
| Spag Sauce | Creole Sauce | 0.51031 |
| Spag Sauce | Salsa | 0.50000 |
| Spag Sauce | Enchilada Sauce | 0.12500 |
The following statements produce a heat map visualization of the similarity between pairs of recipes:
proc sort data=mylib.SimilarityRecipesOut out=SimilarityRecipesSorted;
by sink source;
run;
proc sgplot data=SimilarityRecipesSorted noautolegend;
title "Cosine Similarity of Recipes";
heatmap y=source x=sink / weight=cosine
colormodel=(white green) outline x2axis;
text y=source x=sink text=cosine / textAttrs=(size=10pt);
xaxis display=none;
x2axis display=(nolabel);
yaxis display=(nolabel) reverse;
run;
Output 2.18.2: Cosine Node Similarity between Recipe Pairs

From the heat map shown in Output 2.18.2, you can conclude that the recipes most similar to the Creole sauce recipe by ingredient cosine similarity are the spaghetti meat sauce and spaghetti sauce recipes. Conversely, the enchilada sauce and eggplant relish recipes have zero cosine similarity because they have no ingredients in common.