In this project, the evolution of countries’ economic spheres of influence over time is explored via graph theory. Several techniques are implemented to visualize trade relationships for specific countries and analyze how these expand to create complex networks. Later, methods are developed to both identify significant changes in networks and calculate parameters that facilitate a better understanding of each country’s role and significance. Finally, an algorithm is developed to simulate economic shock propagation using Input-Output systems and to create visual representations of countries’ interdependence.

Introduction

What Is Economic Influence?

Economic influence refers to a country’s ability to shape global trade flows and impact other countries. Therefore, it can be evaluated based on its role as an exporter, importer, technological hub, etc. Economic influence can shift over time due to multiple factors, such as conflicts, globalization, and policy, and analyzing these changes is essential.

What is a Trade Network?

A trade network is a directed graph, consisting of multiple nodes that represent countries, and edges that represent trade flows. By using graph theory, we can extract significant information from these graphs, which can let us identify trade blocs and structural trends. Thus, these networks are a powerful tool to both model and visualize economic relationships between countries and its evolution through time.

Objectives

This project aims to:
1. Use graphs to model countries’ trade relationships
2. Identify network metrics in these graphs
3. Create ways to visualize changes in these graphs over time
4. Simulate how economic shocks propagate through the networks

Data Acquisition

GDP Data

To evaluate the economic influence of countries through time, it is first necessary to collect reliable data. The first step of this process was retrieving GDP data, which was achieved by using the Wolfram Knowledgebase. The data was imported using EntityProperty, processed to fit the desired format, and stored in a Tabular object. It is important to highlight that Angola, Marshall Islands, and Syria had to be removed since they contained inconsistent data, which could lead to errors in future computations.
Import GDP data for all countries using the Wolfram Knowledgebase:
In[]:=
gdpRawData=Table[​​<|country->country[EntityProperty["Country","GDP",{"Date"->All}]]//Normal|>,​​{country,EntityList[EntityClass["Country","Countries"]]}​​];
Define a function to associate country, year, and GDP:
In[]:=
getCountries[a_]:=Association[Keys[gdpRawData[[a]]]->#]&/@Partition[Flatten[Values[gdpRawData[[a]]]],2];
Apply getCountries to each value in gdpRawData:
In[]:=
associationCountryYearGDP=Table[getCountries[a],{a,Length[gdpRawData]}];
Get a list with all country names:
In[]:=
gdpCountries=Flatten[Keys[associationCountryYearGDP]];
Get a list with all years and GDPs:
In[]:=
listYearGDP=Flatten[Values[associationCountryYearGDP],2];
Get separate lists for years and GDPs:
In[]:=
gdpYears=DateObject[#,"Year"]&/@Table[year[[1]],{year,listYearGDP}];​​gdpValues=Round/@QuantityMagnitude/@Table[gdp[[2]],{gdp,listYearGDP}];
Create a Tabular object with Country, Year, and GDP as columns:
In[]:=
gdpTabularData=ToTabular@Table[​​<|"Country"->CommonName[gdpCountries[[i]]],​​"Year"->ToExpression[DateString[gdpYears[[i]]]],​​"GDP"->gdpValues[[i]]|>,​​{i,Length[gdpCountries]}​​];
Remove countries with inconsistent data:
In[]:=
gdpData=Select[gdpTabularData,!Or[#Country=="Angola",#Country=="Marshall Islands",#Country=="Syria"]&]
Out[]=
Tabular
Row count: 11408
Column count: 3


Trade Data


Data Processing

Standardizing Country Names

After the data was imported and stored in the correct format, the next step would be to merge gdpData and tradeData. However, the names of some of the countries were different in each object, since their sources were different. Therefore, it was first necessary to standardize countries’ names in both objects to guarantee a successful merging process without losing any relevant data. This was conducted by passing in the country name in tradeData to the Wolfram Natural Language Processing, and then getting the common name of the entity that was returned. However, for some specific cases, like Venezuela and the Netherlands, it was necessary to apply some changes to their names so that the NLP could successfully interpret them.
Get all country names in tradeData and change their names so that they match the names in gdpData:
In[]:=
countryList=Normal[tradeData[[All,"Country"]]]//DeleteDuplicates;
Standardize specific country names:
In[]:=
cleanedCountryList=Table[​​Which[​​StringMatchQ[country,RegularExpression[".*, The$"]],<|country->StringDrop[country,-5]|>,​​StringMatchQ[country,RegularExpression[".*, República Bolivariana de$"]],<|country->StringTake[country,9]|>,​​True,<|country->country|>​​],{country,countryList}​​];
Create an association containing the countries’ name in tradeData, the Entity that the Natural Language Processing has interpreted, and the name of that Entity:
In[]:=
countryAssociation=Quiet@Table[​​<|"Country"->Keys[country][[1]],​​"EntityInterpreted"->Interpreter["Country"][Values[country][[1]]],​​"CleanedCountry"->CommonName[Interpreter["Country"][Values[country][[1]]]]|>,​​{country,cleanedCountryList}​​];
Remove countries that were not correctly interpreted:
In[]:=
cleanedCountries=Select[countryAssociation,Not[FailureQ[#["EntityInterpreted"]]]&];
Delete unnecessary columns:
In[]:=
countryTabular=ToTabular[DeleteColumns[cleanedCountries,{"EntityInterpreted"}]]
Out[]=
Tabular
Row count: 195
Column count: 2

Now, we can apply the same process to the counterpart countries.
Standardize counterpart countries’ names:
In[]:=
counterpartCountryList=Normal[tradeData[[All,"CounterpartCountry"]]]//DeleteDuplicates;​​cleanedCounterpartCountryList=Table[​​Which[​​StringMatchQ[country,RegularExpression[".*, The$"]],<|country->StringDrop[country,-5]|>,​​StringMatchQ[country,RegularExpression[".*, República Bolivariana de$"]],<|country->StringTake[country,9]|>,​​True,<|country->country|>​​],{country,counterpartCountryList}​​];​​counterpartCountryAssociation=Quiet@Table​​ <|"CounterpartCountry"->Keys[country][[1]],​​"EntityInterpreted"->Interpreter["Country"][Values[country][[1]]],​​"CleanedCounterpartCountry"->CommonName[Interpreter["Country"][Values[country][[1]]]]|>,​​{country,cleanedCounterpartCountryList}​​;​​cleanedCounterpartCountries=Select[counterpartCountryAssociation,Not[FailureQ[#["EntityInterpreted"]]]&];​​counterpartCountryTabular=ToTabular[DeleteColumns[cleanedCounterpartCountries,{"EntityInterpreted"}]]
Out[]=
Tabular
Row count: 195
Column count: 2


Merging Datasets

Now that I had the correct names for each country, it was necessary to standardize country names in both Tabular objects so that they could be merged. To do so, countryTabular and counterpartCountryTabular were initially merged with tradeData, and then the resulting dataset was merged with gdpData. Finally, all columns were converted to units instead of millions to ensure that they were all standardized.
Define three variables to store the datasets that will be merged:
In[]:=
ds1=Dataset[countryTabular];​​ds2=Dataset[counterpartCountryTabular];​​ds3=Dataset[tradeData];
Merge the trade dataset with clean names:
In[]:=
joinedTrade=ToTabular@Normal[ds3//JoinAcross[#,ds1,{"Country"}]&//JoinAcross[#,ds2,{"CounterpartCountry"}]&];
Replace country and counterpart country names with their cleaned versions:
In[]:=
standardizedNames=TransformColumns[​​joinedTrade,​​{"Country"->(#CleanedCountry&),"CounterpartCountry"->(#CleanedCounterpartCountry&)}​​];
Delete unnecessary columns:
In[]:=
cleanedNamesData=DeleteColumns[standardizedNames,{"CleanedCountry","CleanedCounterpartCountry"}];
Merge gdpData and cleanedNamesData:
In[]:=
dsJ=Dataset[gdpData];​​dsO=Dataset[cleanedNamesData];​​merged=ToTabular[Normal[JoinAcross[dsJ,dsO,{"Country","Year"}]]];
Transform columns so that all values are in units:

Graphing Trade Networks

Creating Trade Graphs

Once all data was collected, it was possible to start graphing. Initially, I decided to start by creating trade networks with depth 1. This means that, starting from a country A, our goal is to create a graph showcasing the top X countries that it trades the most, according to the selected operation: imports, exports or trade balance. Additionally, the graph’s edges represent the amount of trade between two countries, through both color (red represents a lot of trade, blue represents a little) and size (the larger the width of the arrow, the higher the amount of trade between the two countries).
Start by defining relevant variables (inputs):
Select transactions according to the input:
Get lists of countries and counterpart countries:
Create an association with country and counterpart country according to the selected operation:
Get a list containing the value of all selected transactions:
Define values for graph edges hues and thicknesses based on transactions:
Create the graph:
We can now combine these elements into a function.
Function to graph transactions for a certain country:
Plot Brazil’s trade network in 2005 for exports, selecting the 10 largest trading partners:

Implementing Recursion

Up to this point, we have been graphing trade between two countries with depth 1. In other words, we are only graphing trade for the country specified by the user, without going further into the network. However, to better evaluate the economic influence of a country, we need to understand the indirect influences that countries might exert in one-another by graphing trade relationships with depth. This means that our next goal is to comprehend with which countries each of one of the leaves of the graph we created earlier trades the most, and then repeat this process multiple times. This can be achieved by using a recursive approach, which will be explained in detail in this section.
Create a recursive function to get all desired transactions in a network:
Let's now understand what is going on.
We start by defining the inputs:
Initialize empty lists:
Define the base case:
Apply the same depth-1 approach:
Accumulate current layer:
Apply the recursive step by calling the function to each counterpart country with depth subtracted by one:
Return a list containing the edges, transactions, hues and thicknesses for graph plotting:
Now, we need to implement a recursive helper. This is the function that will actually be called by the user, which will call the recursive function, get its result, and graph it.
Initialize variables with empty lists:
Call recursiveGraphData with depth subtracted by one:
Parse recursiveGraphData output :
Filter out duplicate edges while preserving the first occurrence of their associated transaction, color, and thickness data:
Iterate through edge data and keep only the first occurrence of each unique edge, storing its associated transaction, color, and thickness:
Graph the association:
We can now combine everything into a function.
Function to graph transactions with depth:
Graph exports for Brazil in 2005 with depth 3 getting top 4 trading countries for each:

Identifying Significant Changes

Now that we are are able to create trade networks with larger depths, it is time to start identifying changes in those networks, so that we can actually compare graphs from different years. This will enable us to identify global economic transformations. To do this, we create a function called compareGraphs that uses operations such as Complement and Intersection to find changes in graphs, and then returns information about the edges that were created, deleted, or significantly changed.
Define variables for inputs:
Get graph data for each year:
Associate each value in one year to its corresponding value in the other year:
Get the keys of each association:
Compute new edges:
Compute removed edges:
Compute common edges:
Compute changed edges:
Create a report with all calculated values:
We now combine all of this into a function.
Function to compare the graph of a certain country in two different years:
Within the report generated by compareGraphs:
◼
  • NewEdges: contains the edges that did not exist in the first year, but exist in the second year;
  • ◼
  • This means that a certain counterpart country is not included anymore in the top trading partners of a country.
  • ◼
  • RemovedEdges: contains the edges that existed in the first year, but do not exist in the second year;
  • ◼
  • This means that a new counterpart country was included in the top trading partners of a country in the second year.
  • ◼
  • ChangedEdges: contains the edges whose weights that were significantly changed from the first year to the second year;
  • ◼
  • This means that the amount of trade between two countries suffered significant changes from the first year to the second year.
  • ◼
  • Summary: contains the number of elements in each one of the above lists.
  • Compare import graphs for Peru in 2005 and 2020:
    However, it would be interesting to have a more visual representation of this data. To do this, we can create a function that is capable of implementing this same logic, but using the data to plot a graph.
    Apply the same approach as compareGraphs:
    Compute unchanged edges:
    Join all computed edges:
    Define edge colors for each type of edge:
    Plot the graph:
    Now, we combine all this logic into a function.
    Function to plot changes in the graph of a certain country:
    Within the graph:
    ◼
  • Green edges represent new connections;
  • ◼
  • Red edges represent removed connections;
  • ◼
  • Blue edges represent connections with significant changes in value;
  • ◼
  • Gray edges represent connections that remained practically unchanged.
  • Plot changes in Peru’s import graph for 2005 and 2020:

    Selecting Relevant Metrics

    One of the advantages of using graphs to model real-world scenarios is the incredible amount of metrics that can be easily calculated using Wolfram Language. Here, we will analyze a few metrics to demonstrate how they can be used to get insights about trading relationships.
    We start by analyzing network structure metrics, which provide information on the network as a whole. The most frequently used metrics are:
    ◼
  • Density: ratio of actual edges to possible edges;
  • ◼
  • Diameter: longest shortest path between any two nodes;
  • ◼
  • Average Degree: average number of connections for each node;
  • ◼
  • Modularity: how well the network separates into distinct communities.
  • In an economics scenario, density represents how interconnected trade is, diameter shows the size of the network, average degree represents the average number of trading partners, and modularity varies according to how well the network separates into distinct trade blocs or communities.
    Function to determine a graph’s structure metrics:
    Subsequently, we collect data about countries’ centrality in the graph, which are metrics that can be used to evaluate their influence. The fours parameters that were chose were:
    ◼
  • In-Degree: represents the amount of connections arriving at the node (in our case, imports);
  • ◼
  • Out-Degree: represents the amount of connections leaving the node (in our case, exports);
  • ◼
  • Page Rank: used to evaluate a country’s overall importance in the network, based both on quantity and quality of the connections
  • ◼
  • For instance, a country that trades with the U.S. and China, even if not trading much itself, can have high PageRank.
  • ◼
  • Betweenness Centrality: measures how often a country lies on the shortest paths between other country pairs, acting as “bridges”.
  • Function to calculate centrality data:
    We can then combine some of our own functions with some of Wolfram Language’s built-in functions to get some relevant information.
    Plot the trade balance graph for the United States in 2022:
    Find communities inside the graph:
    Calculate the graph’s network metrics:
    Determine centrality data for each country in the graph:
    Finally, we can visualize the communities in the graph using CommunityGraphPlot.
    Visualize communities inside our graph:

    Simulating Shock Propagation

    Adding necessary columns

    Now that our graphs are ready, we can start simulating shock propagation through the network. Economic shocks are defined as sudden, unexpected events that cause positive or negative impacts in a country’s economy. The approach that was chosen to model these scenarios was inspired by the Leontief Input-Output Model, where shocks in one country can affect others through their economic interdependencies. In the Leontief model, the propagation follows the following equation:
    ◼
  • (I - A) X = F
  • ◼
  • I: identity matrix
  • ◼
  • A: input coefficient matrix
  • ◼
  • X: total output vector (what each country/sector produces)
  • ◼
  • F: final demand vector
  • To implement a similar process with data that was available, we decided to modify this model while maintaining a similar concept, where shocks in one country can impact other countries indirectly. This was achieved by creating the three equations below:
    ◼
  • Influence(A->B) = Trade(A-B) / TotalTrade
  • ◼
  • PropagatedShock(B) = OriginShock(A) x Influence(A->B)
  • ◼
  • UpdatedGDP(B) = GDP(B) + (GDP(B) x PropagatedShock(B)
  • As you can see, to update a country’s GDP according to these equations, we calculate the propagated shock by multiplying the original shock by the influence/interdependence between the two countries. This influence is given by the share of the total trade of a country that this specific counterpart country represents.
    It is important to highlight that this model requires a few things to work. First, we need to be able to retrieve GDP data for any country in a given year, which can be done using the Tabular objects that we defined earlier. However, we also need to know the share of the total trade that each counterpart country represents in every year, and this is currently not available in our database. Thus, we need to modify our Tabular objects to include this information before implementing our algorithm.
    We start by classifying each country as “Importer” or “Exporter” based on its trade balance with a counterpart:
    Add a column with the absolute value of the trade balance for each counterpart country:
    Replace missing values with zeros:
    Group data by country and year, summing absolute trade balances with all counterparts:
    Add absolute trade balance per country-year to each row:
    Calculate each counterpart’s share of a country’s absolute trade balance:
    Initialize the values for the UpdatedGDPDomestic column with the same values as GDPDomestic:

    Visualizing countries’ influence

    Now that we are able to propagate a shock, we should develop ways of visualizing which countries were the most impacted by that shock. This will allow us to evaluate the economic spheres of influence of each country, since counterpart countries in their sphere of influence should be more affected by economic shocks. Finally, this will also help us identify countries that are highly dependent on others, as well as countries that have a strong economic independence.
    Define input variables:
    Create a new column with the shock’s impact in each country:
    Create another column with the absolute value of the shock:
    Remove countries that were not affected at all by the shock:
    Sort data from impactedCountries from most to least affected countries:
    Delete the country of origin from mostAffectedCountries:
    Create a list containing the shock’s impact for each country in mostAffectedCountries:
    Create a list of the graph edges:
    Calculate the hues and thicknesses of graph edges according to the intensity of the shock in each country:
    Create the graph:
    Now, we combine everything into a function:
    Function to plot the influence of a country given a specific shock:
    Call influencePlot to graph the shock that was propagated earlier:

    Conclusions

    As shown in the previous sections, the usage of graphs to represent and visualize trade networks, as well as the evolution of countries’ economic influence through time, was very successful. Multiple visualizations were created, and many others could be developed using the existing ones as a basis. Furthermore, the simulations of shock propagation were successfully conducted, proving that graph theory can be used to model these scenarios. However, some simplifications in the propagation rules—such as linear influence weighting and absence of real-time feedback—may limit the model’s real-world accuracy, and therefore, further testing should be conducted to evaluate the precision of this algorithm when compared to its peers. These findings demonstrate how network sciences and graph theory can be used to understand shock diffusion and systemic risk in global economics.

    Future Directions

    To further improve this project, more financial data, such as Foreign Direct Investment and debt, could be included to make the predictions more accurate, and new visualization methods, such as interactive maps and animations, could be added to better understand these scenarios. It would also be possible to implement simulation mechanisms for multiple sequential shocks, and conduct empirical validation using historical crises, such as COVID. Finally, it would be possible to create other simulation methods, such as Graph Neural Networks or Leontief Input-Output Modeling, and compare their results to the original method. These additions would enable us to identify global patterns, such as changes in economic blocs and (de)centralization processes.

    References

    ◼
  • Starnini M., Boguñá M., & Serrano M.Á. (2019). The interconnected wealth of nations: Shock propagation on global trade‑investment multiplex networks. Scientific Reports, 9, 13079. https://doi.org/10.1038/s41598-019-49173-2
  • ◼
  • Martha G. Alatriste Contreras and Giorgio Fagiolo. Propagation of Economic Shocks in Input‑Output Networks: A Cross‑Country Analysis. https://arxiv.org/abs/1401.4704
  • ◼
  • Jiankui He and Michael W. Deem. Structure and Response in the World Trade Network. Physical Review Letters, 105(19), 198701 (2010). https://doi.org/10.1103/PhysRevLett.105.198701
  • ◼
  • Federica Cerina, Zhen Zhu, Alessandro Chessa & Massimo Riccaboni. World Input-Output Network. https://arxiv.org/abs/1407.0225
  • Acknowledgements

    I would first like to thank my amazing mentor Carlos Angulo for providing me with the tools and background that allowed me to explore this project, while creating an amazing learning environment for us to work on. I would also like to thank TA Alisa Zaitseva for the essential help in the data acquisition and processing stages, and Gregory Roudenko for his contribution to the recursive algorithm for shock propagation. Finally, I would like to thank all the directors, mentors, and teaching assistants that made this summer program possible.

    CITE THIS NOTEBOOK

    Simulating macroeconomic shock propagation in interconnected economies​
    by Leonardo Bartoccini​
    Wolfram Community, STAFF PICKS, July 10, 2025
    ​https://community.wolfram.com/groups/-/m/t/3502384