{"id":1031,"date":"2026-02-21T20:24:21","date_gmt":"2026-02-21T20:24:21","guid":{"rendered":"https:\/\/inphronesys.com\/?p=1031"},"modified":"2026-02-21T20:36:55","modified_gmt":"2026-02-21T20:36:55","slug":"network-analysis-for-supply-chain-risk-and-resilience","status":"publish","type":"post","link":"https:\/\/inphronesys.com\/?p=1031","title":{"rendered":"Network Analysis for Supply Chain Risk and Resilience"},"content":{"rendered":"<h2>Your Supply Chain Is a Graph<\/h2>\n<p>Every supply chain is a network of relationships: raw material suppliers feed component manufacturers, who supply assembly plants, who ship through distribution centers to end markets. You manage this network every day \u2014 but do you actually <em>see<\/em> it?<\/p>\n<p>Most supply chain visibility tools show you lists. Lists of suppliers, lists of orders, lists of shipments. What they do not show you is the <em>structure<\/em> \u2014 the web of dependencies that determines how a disruption at one node cascades through the entire system.<\/p>\n<p>Network analysis, rooted in graph theory, gives you that structural view. It answers questions that no ERP report can:<\/p>\n<ul>\n<li>Which supplier is the single point of failure for the most end markets?<\/li>\n<li>If a key node goes down, how many supply paths are severed?<\/li>\n<li>Which clusters of suppliers form tightly connected groups \u2014 and what does that mean for risk concentration?<\/li>\n<\/ul>\n<p>R&#8217;s <code>igraph<\/code> package makes this analysis accessible. In this post, we build a multi-tier supply chain network from scratch and apply the methods that reveal hidden vulnerabilities.<\/p>\n<h2>Building a Multi-Tier Supply Chain Network<\/h2>\n<p>We model a supply chain with five tiers: raw material suppliers, component suppliers, manufacturers, distribution centers, and end markets. The relationships between them are directional \u2014 material flows downstream from raw suppliers to markets.<\/p>\n<pre><code class=\"language-r\">library(igraph)\n\nset.seed(42)\n\n# Define the five tiers\nraw_suppliers  &lt;- paste0(&quot;Raw-&quot;, 1:6)\ncomp_suppliers &lt;- paste0(&quot;Comp-&quot;, 1:8)\nmanufacturers  &lt;- paste0(&quot;Mfg-&quot;, 1:3)\ndistributors   &lt;- paste0(&quot;DC-&quot;, 1:4)\ncustomers      &lt;- paste0(&quot;Market-&quot;, 1:5)\n\n# Define supply relationships (edges)\nedges &lt;- data.frame(\n  from = c(\n    &quot;Raw-1&quot;,&quot;Raw-1&quot;,&quot;Raw-2&quot;,&quot;Raw-2&quot;,&quot;Raw-3&quot;,&quot;Raw-3&quot;,\n    &quot;Raw-4&quot;,&quot;Raw-4&quot;,&quot;Raw-5&quot;,&quot;Raw-5&quot;,&quot;Raw-6&quot;,&quot;Raw-6&quot;,\n    &quot;Comp-1&quot;,&quot;Comp-1&quot;,&quot;Comp-2&quot;,&quot;Comp-2&quot;,&quot;Comp-3&quot;,&quot;Comp-3&quot;,\n    &quot;Comp-4&quot;,&quot;Comp-5&quot;,&quot;Comp-5&quot;,&quot;Comp-6&quot;,&quot;Comp-7&quot;,&quot;Comp-8&quot;,\n    &quot;Comp-4&quot;,&quot;Comp-7&quot;,\n    &quot;Mfg-1&quot;,&quot;Mfg-1&quot;,&quot;Mfg-2&quot;,&quot;Mfg-2&quot;,&quot;Mfg-3&quot;,&quot;Mfg-3&quot;,&quot;Mfg-3&quot;,\n    &quot;DC-1&quot;,&quot;DC-1&quot;,&quot;DC-2&quot;,&quot;DC-2&quot;,&quot;DC-3&quot;,&quot;DC-3&quot;,&quot;DC-4&quot;,&quot;DC-4&quot;\n  ),\n  to = c(\n    &quot;Comp-1&quot;,&quot;Comp-2&quot;,&quot;Comp-2&quot;,&quot;Comp-3&quot;,&quot;Comp-4&quot;,&quot;Comp-5&quot;,\n    &quot;Comp-5&quot;,&quot;Comp-6&quot;,&quot;Comp-7&quot;,&quot;Comp-8&quot;,&quot;Comp-8&quot;,&quot;Comp-1&quot;,\n    &quot;Mfg-1&quot;,&quot;Mfg-2&quot;,&quot;Mfg-1&quot;,&quot;Mfg-3&quot;,&quot;Mfg-2&quot;,&quot;Mfg-3&quot;,\n    &quot;Mfg-1&quot;,&quot;Mfg-2&quot;,&quot;Mfg-3&quot;,&quot;Mfg-3&quot;,&quot;Mfg-1&quot;,&quot;Mfg-2&quot;,\n    &quot;Mfg-2&quot;,&quot;Mfg-3&quot;,\n    &quot;DC-1&quot;,&quot;DC-2&quot;,&quot;DC-2&quot;,&quot;DC-3&quot;,&quot;DC-3&quot;,&quot;DC-4&quot;,&quot;DC-1&quot;,\n    &quot;Market-1&quot;,&quot;Market-2&quot;,&quot;Market-2&quot;,&quot;Market-3&quot;,\n    &quot;Market-3&quot;,&quot;Market-4&quot;,&quot;Market-4&quot;,&quot;Market-5&quot;\n  )\n)\n\nedges$weight &lt;- sample(10:100, nrow(edges), replace = TRUE)\n\nall_nodes &lt;- c(raw_suppliers, comp_suppliers, manufacturers,\n               distributors, customers)\n\ng &lt;- graph_from_data_frame(edges, directed = TRUE,\n                           vertices = data.frame(name = all_nodes))\n<\/code><\/pre>\n<p>The result is a directed graph with 26 nodes and 41 edges spanning five tiers. Each edge represents a supply relationship, and the weight represents relative volume or importance.<\/p>\n<h2>Visualizing the Network Structure<\/h2>\n<p>The first step is to see the network as a whole. We color nodes by tier and size edges by volume:<\/p>\n<pre><code class=\"language-r\">V(g)$tier &lt;- ifelse(grepl(&quot;Raw&quot;, V(g)$name), &quot;Raw Material&quot;,\n             ifelse(grepl(&quot;Comp&quot;, V(g)$name), &quot;Component&quot;,\n             ifelse(grepl(&quot;Mfg&quot;, V(g)$name), &quot;Manufacturer&quot;,\n             ifelse(grepl(&quot;DC&quot;, V(g)$name), &quot;Distribution&quot;,\n                    &quot;Market&quot;))))\n\ntier_colors &lt;- c(&quot;Raw Material&quot; = &quot;#2196F3&quot;, &quot;Component&quot; = &quot;#4CAF50&quot;,\n                 &quot;Manufacturer&quot; = &quot;#FF9800&quot;, &quot;Distribution&quot; = &quot;#9C27B0&quot;,\n                 &quot;Market&quot; = &quot;#F44336&quot;)\n\nV(g)$color &lt;- tier_colors[V(g)$tier]\n\nplot(g,\n     layout       = layout_with_sugiyama(g, layers = tier_order)$layout,\n     vertex.size  = 18,\n     vertex.color = V(g)$color,\n     edge.arrow.size = 0.4,\n     edge.width   = E(g)$weight \/ 30,\n     main = &quot;Multi-Tier Supply Chain Network&quot;)\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_full_scm.png\" alt=\"Multi-Tier Supply Chain Network\" \/><\/p>\n<p>The Sugiyama layout arranges nodes left-to-right by tier, so the material flow direction is immediately visible. Several structural patterns stand out:<\/p>\n<ul>\n<li><strong>Convergence at the manufacturer tier.<\/strong> Eight component suppliers funnel into just three manufacturers. This is the narrowest point in the network \u2014 and the most vulnerable.<\/li>\n<li><strong>Fan-out at distribution.<\/strong> Three manufacturers feed four DCs, which serve five markets. The downstream network is more resilient because multiple paths exist.<\/li>\n<li><strong>Uneven connectivity.<\/strong> Some component suppliers (Comp-1, Comp-2, Comp-5) feed multiple manufacturers, while others (Comp-6, Comp-8) connect to only one. The latter are less critical to the network but also less flexible if their single customer fails.<\/li>\n<\/ul>\n<h2>Finding Critical Nodes with Centrality Analysis<\/h2>\n<p>Not all nodes in a supply chain are equally important. <strong>Betweenness centrality<\/strong> measures how many shortest paths between all pairs of nodes pass through a given node. A node with high betweenness is a chokepoint \u2014 if it fails, many supply paths are disrupted.<\/p>\n<pre><code class=\"language-r\">bet &lt;- betweenness(g, directed = TRUE)\ndeg &lt;- degree(g, mode = &quot;all&quot;)\n\ncentrality_df &lt;- data.frame(\n  node        = V(g)$name,\n  tier        = V(g)$tier,\n  degree      = deg,\n  betweenness = round(bet, 1)\n)\n\ncentrality_df[order(-centrality_df$betweenness), ]\n<\/code><\/pre>\n<pre><code>        node         tier degree betweenness\n     Mfg-3  Manufacturer      8        58.0\n     Mfg-1  Manufacturer      6        33.0\n     DC-1   Distribution      4        29.0\n     Mfg-2  Manufacturer      7        24.0\n     DC-3   Distribution      4        20.0\n     Comp-1    Component      4        18.0\n     DC-2   Distribution      4        16.0\n     Comp-7    Component      3        11.0\n     DC-4   Distribution      3        11.0\n     Comp-2    Component      4         9.0\n<\/code><\/pre>\n<p>Mfg-3 dominates the betweenness ranking. It sits at the intersection of the most supply paths \u2014 five inbound connections from component suppliers and three outbound connections to distribution centers. This is your most critical node.<\/p>\n<p>We can visualize this by scaling node size to betweenness:<\/p>\n<pre><code class=\"language-r\">node_size &lt;- 10 + (bet \/ max(bet)) * 25\n\nplot(g, layout = layout,\n     vertex.size  = node_size,\n     vertex.color = V(g)$color,\n     main = &quot;Betweenness Centrality \u2014 Node Size = Criticality&quot;)\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_centrality.png\" alt=\"Betweenness Centrality Map\" \/><\/p>\n<p>The manufacturers visually dominate the map because they are the chokepoints. Distribution centers also show significant betweenness \u2014 they control access to end markets. Raw material suppliers and end markets have zero betweenness because they sit at the network edges.<\/p>\n<p>A bar chart makes the ranking explicit:<\/p>\n<pre><code class=\"language-r\">library(ggplot2)\n\ntop_10 &lt;- centrality_df[order(-centrality_df$betweenness), ][1:10, ]\ntop_10$node &lt;- factor(top_10$node, levels = rev(top_10$node))\n\nggplot(top_10, aes(x = node, y = betweenness, fill = tier)) +\n  geom_col(width = 0.7) +\n  coord_flip() +\n  scale_fill_manual(values = tier_colors) +\n  labs(title    = &quot;Top 10 Nodes by Betweenness Centrality&quot;,\n       subtitle = &quot;Higher betweenness = more supply paths depend on this node&quot;,\n       x = NULL, y = &quot;Betweenness Centrality&quot;)\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_betweenness_bar.png\" alt=\"Top 10 Nodes by Betweenness Centrality\" \/><\/p>\n<p>For a procurement manager, this chart is a prioritized risk list. The nodes at the top are where you need backup suppliers, safety stock, or dual-sourcing strategies.<\/p>\n<h2>In-Degree and Out-Degree: Who Depends on Whom?<\/h2>\n<p>Degree centrality splits into two components in a directed network:<\/p>\n<ul>\n<li><strong>In-degree<\/strong> \u2014 how many suppliers feed this node (dependency)<\/li>\n<li><strong>Out-degree<\/strong> \u2014 how many customers this node serves (influence)<\/li>\n<\/ul>\n<pre><code class=\"language-r\">deg_df &lt;- data.frame(\n  node       = V(g)$name,\n  tier       = V(g)$tier,\n  in_degree  = degree(g, mode = &quot;in&quot;),\n  out_degree = degree(g, mode = &quot;out&quot;)\n)\n\nggplot(deg_df, aes(x = reorder(node, in_degree + out_degree), fill = tier)) +\n  geom_col(aes(y = out_degree), width = 0.7, alpha = 0.9) +\n  geom_col(aes(y = -in_degree), width = 0.7, alpha = 0.6) +\n  coord_flip() +\n  scale_fill_manual(values = tier_colors) +\n  labs(title = &quot;In-Degree and Out-Degree by Node&quot;,\n       subtitle = &quot;Right = supplies to | Left = receives from&quot;,\n       x = NULL, y = &quot;\\u2190 In-Degree | Out-Degree \\u2192&quot;)\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_degree_dist.png\" alt=\"In-Degree and Out-Degree by Node\" \/><\/p>\n<p>The manufacturers stand out with high values in both directions \u2014 they receive from many and supply to many. This dual dependency makes them critical from both the supply and demand side.<\/p>\n<p>A node with high in-degree and low out-degree (like Market-2 or Market-3) is a demand concentrator \u2014 losing it means losing a significant share of revenue. A node with high out-degree and zero in-degree (the raw material suppliers) is a supply source \u2014 losing it affects everything downstream.<\/p>\n<h2>Disruption Simulation: What Happens When a Critical Node Fails?<\/h2>\n<p>The real power of network analysis is simulation. We can remove the most critical node (Mfg-3) from the network and measure the impact:<\/p>\n<pre><code class=\"language-r\">critical_node &lt;- &quot;Mfg-3&quot;  # Highest betweenness\n\ng_disrupted &lt;- delete_vertices(g, critical_node)\n\nplot(g_disrupted,\n     layout = layout_with_sugiyama(g_disrupted, layers = layer)$layout,\n     vertex.size = 18,\n     vertex.color = V(g_disrupted)$color,\n     main = paste0(&quot;Disruption Scenario: &quot;, critical_node, &quot; Removed&quot;))\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_disrupted.png\" alt=\"Disruption Scenario: Mfg-3 Removed\" \/><\/p>\n<p>The visual impact is immediate. Five component suppliers (Comp-2, Comp-3, Comp-5, Comp-6, Comp-7) lose one of their downstream paths. Some markets now have fewer supply routes reaching them.<\/p>\n<p>The numbers quantify the damage:<\/p>\n<pre><code>Raw-to-Market paths before disruption: 29\nRaw-to-Market paths after disruption:  23\nPaths lost: 6\n<\/code><\/pre>\n<p>Removing a single manufacturer eliminates 21% of all possible raw-to-market supply paths. This is the kind of insight that justifies dual-sourcing investments, strategic inventory buffers, or qualifying backup manufacturers.<\/p>\n<p>In a real supply chain, you would run this simulation for every node with betweenness above a threshold. The result is a vulnerability matrix that tells you exactly which disruptions would hurt the most and where to invest in resilience.<\/p>\n<h2>Community Detection: Finding Natural Clusters<\/h2>\n<p>Community detection algorithms identify groups of nodes that are more densely connected to each other than to the rest of the network. In a supply chain context, these clusters often represent natural supply ecosystems \u2014 groups of suppliers, manufacturers, and distributors that primarily interact with each other.<\/p>\n<pre><code class=\"language-r\">g_undirected &lt;- as_undirected(g, mode = &quot;collapse&quot;)\ncommunities  &lt;- cluster_louvain(g_undirected)\n\nplot(g,\n     layout = layout,\n     vertex.size  = 18,\n     vertex.color = community_colors[membership(communities)],\n     main = paste0(&quot;Community Detection (Louvain) \u2014 &quot;,\n                   max(membership(communities)), &quot; Clusters&quot;))\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_communities.png\" alt=\"Community Detection \u2014 Louvain Clustering\" \/><\/p>\n<pre><code>Cluster 1: Raw-1, Comp-1, Comp-2, Mfg-1, Mfg-3, DC-1, Market-1\nCluster 2: Raw-2, Comp-3\nCluster 3: Raw-3, Raw-4, Comp-4, Comp-5, Comp-6, Mfg-2\nCluster 4: Raw-5, Raw-6, Comp-7, Comp-8\nCluster 5: DC-2, Market-2\nCluster 6: DC-3, DC-4, Market-3, Market-4, Market-5\n<\/code><\/pre>\n<p>For procurement strategy, these clusters reveal:<\/p>\n<ul>\n<li><strong>Cluster 1<\/strong> is the largest and most integrated \u2014 it spans all five tiers. A disruption here has the widest blast radius.<\/li>\n<li><strong>Clusters 2 and 4<\/strong> are isolated upstream groups. If Raw-2 fails, Comp-3 has no alternative source within its cluster. Similarly, Raw-5 and Raw-6 exclusively feed Comp-7 and Comp-8.<\/li>\n<li><strong>Cluster 6<\/strong> is a downstream distribution group. DC-3, DC-4, and three markets form a tightly coupled demand cluster \u2014 they depend on the same upstream manufacturers.<\/li>\n<\/ul>\n<p>This is directly actionable for supplier portfolio management. Clusters with single-source dependencies need diversification. Clusters that span all tiers need monitoring as integrated supply ecosystems.<\/p>\n<h2>From Analysis to Action<\/h2>\n<p>Network analysis turns your supply chain from a list of suppliers into a strategic map. Here is what to do with these results:<\/p>\n<p><strong>1. Protect the chokepoints.<\/strong> Nodes with high betweenness centrality (Mfg-3, Mfg-1, DC-1) are your single points of failure. Dual-source, buffer inventory, or qualify backup capacity at these locations.<\/p>\n<p><strong>2. Run disruption scenarios quarterly.<\/strong> Remove each critical node from the graph and measure path loss. Compare the results against your current risk mitigation investments. If your highest-betweenness node has no backup plan, that is your top priority.<\/p>\n<p><strong>3. Diversify within clusters.<\/strong> Community detection reveals where your supply base is concentrated. If an entire cluster depends on one raw material supplier, a single disruption cascades through the whole group.<\/p>\n<p><strong>4. Monitor degree changes over time.<\/strong> If a supplier&#8217;s in-degree drops (they are losing their own suppliers), that is an early warning signal. If a manufacturer&#8217;s out-degree increases (they are taking on more customers), their capacity may become a constraint for you.<\/p>\n<p><strong>5. Map your real network.<\/strong> The synthetic example here has 26 nodes. Your actual supply chain may have hundreds or thousands. The same igraph methods scale \u2014 betweenness centrality, community detection, and disruption simulation work on networks of any size. Start with your Tier 1 suppliers and expand upstream as data becomes available.<\/p>\n<h2>Getting Started<\/h2>\n<pre><code class=\"language-r\"># Install igraph\ninstall.packages(&quot;igraph&quot;)\nlibrary(igraph)\n\n# Load your own supplier relationship data\nedges &lt;- read.csv(&quot;supplier_relationships.csv&quot;)  # columns: from, to, volume\ng &lt;- graph_from_data_frame(edges, directed = TRUE)\n\n# Immediate analysis\nbetweenness(g, directed = TRUE)     # Find chokepoints\ndegree(g, mode = &quot;all&quot;)             # Find most connected nodes\ncluster_louvain(as_undirected(g))   # Find natural clusters\n\n# Visualize\nplot(g, vertex.size = 10 + betweenness(g) \/ max(betweenness(g)) * 20)\n<\/code><\/pre>\n<p>You need one CSV file: a list of supply relationships with <code>from<\/code> and <code>to<\/code> columns. Every ERP system can export this. Your purchasing records already contain the data \u2014 each purchase order connects a supplier to your company, and your BOMs connect components to finished goods.<\/p>\n<p>The network is already there. You just have not drawn it yet.<\/p>\n<h2>Interactive Dashboard<\/h2>\n<p>Explore the complete analysis in a single view: <a href=\"https:\/\/inphronesys.com\/wp-content\/uploads\/2026\/02\/network_analysis_dashboard.html\">Supply Chain Network Analysis Dashboard<\/a> \u2014 featuring the full network topology, betweenness centrality ranking, disruption simulation, community structure, and a risk heat map, all following Stephen Few&#8217;s dashboard design principles.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Your supply chain is a network. Graph theory and R&#8217;s igraph package reveal which nodes are critical, where single points of failure hide, and how disruptions propagate \u2014 before they happen.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,20],"tags":[109,110,106,107,15,111,108],"class_list":["post-1031","post","type-post","status-publish","format-standard","hentry","category-data-science","category-supply-chain","tag-centrality","tag-graph-theory","tag-igraph","tag-network-analysis","tag-r","tag-resilience","tag-supply-chain-risk"],"_links":{"self":[{"href":"https:\/\/inphronesys.com\/index.php?rest_route=\/wp\/v2\/posts\/1031","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/inphronesys.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/inphronesys.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/inphronesys.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/inphronesys.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1031"}],"version-history":[{"count":2,"href":"https:\/\/inphronesys.com\/index.php?rest_route=\/wp\/v2\/posts\/1031\/revisions"}],"predecessor-version":[{"id":1037,"href":"https:\/\/inphronesys.com\/index.php?rest_route=\/wp\/v2\/posts\/1031\/revisions\/1037"}],"wp:attachment":[{"href":"https:\/\/inphronesys.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1031"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/inphronesys.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1031"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/inphronesys.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1031"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}