social-graphs/graph-inspect/inspect-graph-comparison.ipynb
2026-08-28 14:06:08 +02:00

425 lines
12 KiB
Text

{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Compare interactions graphs\n",
"\n",
"Inspecting interaction and comparing graphs by counting the components, determining the connectivity, clustering and various other metrics. "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Import the graphs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import networkx as nx\n",
"\n",
"casename1 = '...'\n",
"case1 = '...'\n",
"\n",
"casename2 = '...'\n",
"case2 = '...'\n",
"\n",
"# Import the graph\n",
"G1 = nx.read_graphml(f'../datasets/{case1}-dtc-graph.graphml')\n",
"G2 = nx.read_graphml(f'../datasets/{case2}-dtc-graph.graphml')\n",
"\n",
"# Print nodes, edges and density of the graphs\n",
"print(f'G1:\\nNodes: {G1.number_of_nodes()}\\nEdges: {G1.number_of_edges()}\\nDensity: {nx.density(G1):.5f}')\n",
"print(f'G2:\\nNodes: {G2.number_of_nodes()}\\nEdges: {G2.number_of_edges()}\\nDensity: {nx.density(G2):.5f}')"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Remove isolated nodes."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"G1.remove_nodes_from(list(nx.isolates(G1)))\n",
"G2.remove_nodes_from(list(nx.isolates(G2)))\n",
"\n",
"# Print nodes, edges and density of the graphs\n",
"print(f'G1:\\nNodes: {G1.number_of_nodes()}\\nEdges: {G1.number_of_edges()}\\nDensity: {nx.density(G1):.5f}')\n",
"print(f'G2:\\nNodes: {G2.number_of_nodes()}\\nEdges: {G2.number_of_edges()}\\nDensity: {nx.density(G2):.5f}')"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Compute average degree, connectivity, clustering and degree_assortivity. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"\n",
"components1 = list(nx.connected_components(G1))\n",
"\n",
"component_metrics1 = []\n",
"\n",
"for component in components1:\n",
"\n",
" subG = G1.subgraph(component)\n",
"\n",
" num_nodes = subG.number_of_nodes()\n",
" num_edges = subG.number_of_edges()\n",
" average_degree = (2 * num_edges) / num_nodes\n",
" connectivity = nx.node_connectivity(subG)\n",
" clustering = nx.average_clustering(subG)\n",
" degree_assortivity = nx.degree_assortativity_coefficient(subG)\n",
"\n",
" metrics = {\n",
" 'num_nodes': num_nodes,\n",
" 'num_edges': num_edges,\n",
" 'average_degree': average_degree,\n",
" 'connectivity': connectivity,\n",
" 'clustering': clustering,\n",
" 'degree_assortivity': degree_assortivity,\n",
" }\n",
"\n",
" component_metrics1.append(metrics)\n",
"\n",
"df_metric1 = pd.DataFrame(component_metrics1)\n",
"df_metric1.describe()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"components2 = list(nx.connected_components(G2))\n",
"\n",
"component_metrics2 = []\n",
"\n",
"for component in components2:\n",
"\n",
" subG = G2.subgraph(component)\n",
"\n",
" num_nodes = subG.number_of_nodes()\n",
" num_edges = subG.number_of_edges()\n",
" average_degree = (2 * num_edges) / num_nodes\n",
" connectivity = nx.node_connectivity(subG)\n",
" clustering = nx.average_clustering(subG)\n",
" degree_assortivity = nx.degree_assortativity_coefficient(subG)\n",
"\n",
" metrics = {\n",
" 'num_nodes': num_nodes,\n",
" 'num_edges': num_edges,\n",
" 'average_degree': average_degree,\n",
" 'connectivity': connectivity,\n",
" 'clustering': clustering,\n",
" 'degree_assortivity': degree_assortivity,\n",
" }\n",
"\n",
" component_metrics2.append(metrics)\n",
"\n",
"df_metric2 = pd.DataFrame(component_metrics2)\n",
"df_metric2.describe()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Filter out the outliers in the dataframe, based on number of edges."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_metric1_ro = df_metric1[(df_metric1['num_edges'] < 400) & (df_metric1['num_nodes'] > 10)]\n",
"\n",
"df_metric1_ro.describe()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_metric2_ro = df_metric2[(df_metric2['num_edges'] < 400) & (df_metric2['num_nodes'] > 10)]\n",
"\n",
"df_metric2_ro.describe()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Plot the distributions of average degree."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"import numpy as np\n",
"\n",
"plt.figure(figsize=(8, 6))\n",
"\n",
"upper_limit = 1e3\n",
"\n",
"# Define the number of bins\n",
"num_bins = 20\n",
"\n",
"# Calculate the combined range for both datasets\n",
"min_value = min(df_metric1_ro['average_degree'].min(), df_metric2_ro['average_degree'].min())\n",
"max_value = max(df_metric1_ro['average_degree'].max(), df_metric2_ro['average_degree'].max())\n",
"\n",
"# Create bin edges\n",
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
"\n",
"# Create a single plot\n",
"sns.histplot(df_metric1_ro['average_degree'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
"sns.histplot(df_metric2_ro['average_degree'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
"\n",
"# Set y-axis to logarithmic scale\n",
"plt.yscale('log')\n",
"plt.ylim(0.9, upper_limit)\n",
"\n",
"# Set titles and labels\n",
"plt.title('Distribution of average degree (nodes > 10, edges < 400)', fontsize=16)\n",
"plt.xlabel('Average degree')\n",
"plt.ylabel('Count')\n",
"plt.grid()\n",
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
"\n",
"# Add a legend\n",
"plt.legend()\n",
"\n",
"# Show the plot\n",
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
"plt.show()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Plot the distributions of connectivity."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"import numpy as np\n",
"\n",
"plt.figure(figsize=(8, 6))\n",
"\n",
"upper_limit = 1e3\n",
"\n",
"# Define the number of bins\n",
"num_bins = 20\n",
"\n",
"# Calculate the combined range for both datasets\n",
"min_value = min(df_metric1_ro['connectivity'].min(), df_metric2_ro['connectivity'].min())\n",
"max_value = max(df_metric1_ro['connectivity'].max(), df_metric2_ro['connectivity'].max())\n",
"\n",
"# Create bin edges\n",
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
"\n",
"# Create a single plot\n",
"sns.histplot(df_metric1_ro['connectivity'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
"sns.histplot(df_metric2_ro['connectivity'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
"\n",
"# Set y-axis to logarithmic scale\n",
"plt.yscale('log')\n",
"plt.ylim(0.9, upper_limit)\n",
"\n",
"# Set titles and labels\n",
"plt.title('Distribution of connectivity (nodes > 10, edges < 400)', fontsize=16)\n",
"plt.xlabel('Connectivity')\n",
"plt.ylabel('Count')\n",
"plt.grid()\n",
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
"\n",
"# Add a legend\n",
"plt.legend()\n",
"\n",
"# Show the plot\n",
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
"plt.show()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Plot the distributions of clustering."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"import numpy as np\n",
"\n",
"plt.figure(figsize=(8, 6))\n",
"\n",
"upper_limit = 1e3\n",
"\n",
"# Define the number of bins\n",
"num_bins = 20\n",
"\n",
"# Calculate the combined range for both datasets\n",
"min_value = min(df_metric1_ro['clustering'].min(), df_metric2_ro['clustering'].min())\n",
"max_value = max(df_metric1_ro['clustering'].max(), df_metric2_ro['clustering'].max())\n",
"\n",
"# Create bin edges\n",
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
"\n",
"# Create a single plot\n",
"sns.histplot(df_metric1_ro['clustering'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
"sns.histplot(df_metric2_ro['clustering'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
"\n",
"# Set y-axis to logarithmic scale\n",
"plt.yscale('log')\n",
"plt.ylim(0.9, upper_limit)\n",
"\n",
"# Set titles and labels\n",
"plt.title('Distribution of clustering (nodes > 10, edges < 400)', fontsize=16)\n",
"plt.xlabel('Clustering')\n",
"plt.ylabel('Count')\n",
"plt.grid()\n",
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
"\n",
"# Add a legend\n",
"plt.legend()\n",
"\n",
"# Show the plot\n",
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
"plt.show()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Plot the distributions of degree assortivity."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"import numpy as np\n",
"\n",
"plt.figure(figsize=(8, 6))\n",
"\n",
"upper_limit = 1e3\n",
"\n",
"# Define the number of bins\n",
"num_bins = 20\n",
"\n",
"# Calculate the combined range for both datasets\n",
"min_value = min(df_metric1_ro['degree_assortivity'].min(), df_metric2_ro['degree_assortivity'].min())\n",
"max_value = max(df_metric1_ro['degree_assortivity'].max(), df_metric2_ro['degree_assortivity'].max())\n",
"\n",
"# Create bin edges\n",
"bins = np.linspace(min_value, max_value, num_bins + 1)\n",
"\n",
"# Create a single plot\n",
"sns.histplot(df_metric1_ro['degree_assortivity'], bins=bins, color='blue', alpha=0.5, label=f'{casename1.title()} case')\n",
"sns.histplot(df_metric2_ro['degree_assortivity'], bins=bins, color='orange', alpha=0.5, label=f'{casename2.title()} case')\n",
"\n",
"# Set y-axis to logarithmic scale\n",
"plt.yscale('log')\n",
"plt.ylim(0.9, upper_limit)\n",
"\n",
"# Set titles and labels\n",
"plt.title('Distribution of degree assortivity (nodes > 10, edges < 400)', fontsize=16)\n",
"plt.xlabel('Degree assortivity')\n",
"plt.ylabel('Count')\n",
"plt.grid()\n",
"plt.tick_params(axis='both', direction='in', top=True, right=True)\n",
"\n",
"# Add a legend\n",
"plt.legend()\n",
"\n",
"# Show the plot\n",
"plt.tight_layout(rect=[0, 0, 1, 0.99])\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.14.6"
},
"vscode": {
"interpreter": {
"hash": "8c75c0fdd1a718867cdcb84b32adcfdbeaad00b3a4e00a59385211aeed084d4c"
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}