{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Inspect interaction graphs\n", "\n", "Inspecting interaction graphs by counting the components, determining the connectivity, clustering and various other metrics. " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Import the graph." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import networkx as nx\n", "\n", "casename = '...'\n", "case = '...'\n", "\n", "# Import the graph\n", "G = nx.read_graphml(f'../datasets/{case}-dtc-graph.graphml')\n", "\n", "# Print nodes, edges and density of the graph\n", "print(f'Nodes: {G.number_of_nodes()}\\nEdges: {G.number_of_edges()}\\nDensity: {nx.density(G):.5f}')" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Remove isolated nodes." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "G.remove_nodes_from(list(nx.isolates(G)))\n", "print(f'Nodes: {G.number_of_nodes()}\\nEdges: {G.number_of_edges()}\\nDensity: {nx.density(G):.5f}')" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Compute number of connected components." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nx.number_connected_components(G)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Compute metrics of each component." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "\n", "components = list(nx.connected_components(G))\n", "\n", "component_metrics = []\n", "\n", "for component in components:\n", "\n", " subG = G.subgraph(component)\n", "\n", " num_nodes = subG.number_of_nodes()\n", " num_edges = subG.number_of_edges()\n", " diameter = nx.diameter(subG)\n", " average_degree = (2 * num_edges) / num_nodes\n", " density = nx.density(subG)\n", " connectivity = nx.node_connectivity(subG)\n", " clustering = nx.average_clustering(subG)\n", " degree_assortivity = nx.degree_assortativity_coefficient(subG)\n", " sentiment_assortivity = nx.numeric_assortativity_coefficient(subG, 'sentiment')\n", "\n", " metrics = {\n", " 'num_nodes': num_nodes,\n", " 'num_edges': num_edges,\n", " 'diameter': diameter,\n", " 'average_degree': average_degree,\n", " 'density': density,\n", " 'connectivity': connectivity,\n", " 'clustering': clustering,\n", " 'degree_assortivity': degree_assortivity,\n", " 'sentiment_assortivity': sentiment_assortivity\n", " }\n", "\n", " component_metrics.append(metrics)\n", "\n", "df_metric = pd.DataFrame(component_metrics)\n", "df_metric.describe()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Plot the distribution of the metrics." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "\n", "plt.figure(figsize=(15, 15))\n", "\n", "upper_limit = 1e5\n", "\n", "plt.subplot(3, 3, 1)\n", "sns.histplot(df_metric['num_nodes'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of nodes')\n", "plt.xlabel('Number of nodes')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 2)\n", "sns.histplot(df_metric['num_edges'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of edges')\n", "plt.xlabel('Number of edges')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 3)\n", "sns.histplot(df_metric['diameter'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of diameter')\n", "plt.xlabel('Diameter')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 4)\n", "sns.histplot(df_metric['average_degree'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of average degree')\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", "plt.subplot(3, 3, 5)\n", "sns.histplot(df_metric['density'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(1e1, upper_limit)\n", "plt.title('Distribution of density')\n", "plt.xlabel('Density')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 6)\n", "sns.histplot(df_metric['connectivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of connectivity')\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", "plt.subplot(3, 3, 7)\n", "sns.histplot(df_metric['clustering'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of clustering')\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", "plt.subplot(3, 3, 8)\n", "sns.histplot(df_metric['degree_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of degree assortivity')\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", "plt.subplot(3, 3, 9)\n", "sns.histplot(df_metric['sentiment_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of sentiment assortivity')\n", "plt.xlabel('Sentiment assortivity')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.suptitle(f'Metrics {casename} case', fontsize=16)\n", "plt.tight_layout(rect=[0, 0, 1, 0.99])\n", "\n", "plt.savefig(f'../datasets/{case}-metrics.png')\n", "plt.show()" ] }, { "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_metric_ro = df_metric[df_metric['num_edges'] < 400]\n", "\n", "df_metric_ro.describe()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Plot the distribution of the metrics of the outlier filtered dataframe." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Set up the matplotlib figure\n", "plt.figure(figsize=(15, 15))\n", "\n", "upper_limit = 1e5\n", "\n", "# Plot distributions\n", "plt.subplot(3, 3, 1)\n", "sns.histplot(df_metric_ro['num_nodes'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of nodes')\n", "plt.xlabel('Number of nodes')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 2)\n", "sns.histplot(df_metric_ro['num_edges'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of edges')\n", "plt.xlabel('Number of edges')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 3)\n", "sns.histplot(df_metric_ro['diameter'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of diameter')\n", "plt.xlabel('Diameter')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 4)\n", "sns.histplot(df_metric_ro['average_degree'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of average degree')\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", "plt.subplot(3, 3, 5)\n", "sns.histplot(df_metric_ro['density'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(1e1, upper_limit)\n", "plt.title('Distribution of density')\n", "plt.xlabel('Density')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 6)\n", "sns.histplot(df_metric_ro['connectivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of connectivity')\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", "plt.subplot(3, 3, 7)\n", "sns.histplot(df_metric_ro['clustering'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of clustering')\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", "plt.subplot(3, 3, 8)\n", "sns.histplot(df_metric_ro['degree_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of degree assortivity')\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", "plt.subplot(3, 3, 9)\n", "sns.histplot(df_metric_ro['sentiment_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of sentiment assortivity')\n", "plt.xlabel('Sentiment assortivity')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.suptitle(f'Metrics (edges < 400) {casename} case', fontsize=16)\n", "plt.tight_layout(rect=[0, 0, 1, 0.99])\n", "\n", "plt.savefig(f'../datasets/{case}-metrics-ro.png')\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Filter metrics on number of nodes." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_metric_ls = df_metric[df_metric['num_nodes'] > 10]\n", "\n", "df_metric_ls.describe()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Plot the distribution of the metrics of the large structures set." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Set up the matplotlib figure\n", "plt.figure(figsize=(15, 15))\n", "\n", "upper_limit = 1e3\n", "\n", "# Plot distributions\n", "plt.subplot(3, 3, 1)\n", "sns.histplot(df_metric_ls['num_nodes'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of nodes')\n", "plt.xlabel('Number of nodes')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 2)\n", "sns.histplot(df_metric_ls['num_edges'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of edges')\n", "plt.xlabel('Number of edges')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 3)\n", "sns.histplot(df_metric_ls['diameter'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of diameter')\n", "plt.xlabel('Diameter')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 4)\n", "sns.histplot(df_metric_ls['average_degree'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of average degree')\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", "plt.subplot(3, 3, 5)\n", "sns.histplot(df_metric_ls['density'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(1e1, upper_limit)\n", "plt.title('Distribution of density')\n", "plt.xlabel('Density')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 6)\n", "sns.histplot(df_metric_ls['connectivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of connectivity')\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", "plt.subplot(3, 3, 7)\n", "sns.histplot(df_metric_ls['clustering'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of clustering')\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", "plt.subplot(3, 3, 8)\n", "sns.histplot(df_metric_ls['degree_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of degree assortivity')\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", "plt.subplot(3, 3, 9)\n", "sns.histplot(df_metric_ls['sentiment_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of sentiment assortivity')\n", "plt.xlabel('Sentiment assortivity')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.suptitle(f'Metrics (nodes > 10) {casename} case', fontsize=16)\n", "plt.tight_layout(rect=[0, 0, 1, 0.99])\n", "\n", "plt.savefig(f'../datasets/{case}-metrics-ls.png')\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Filter out the outliers in the large structures dataset, based on number of edges." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_metric_ls_ro = df_metric_ls[df_metric_ls['num_edges'] < 400]\n", "\n", "df_metric_ls_ro.describe()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Set up the matplotlib figure\n", "plt.figure(figsize=(15, 15))\n", "\n", "upper_limit = 1e3\n", "\n", "# Plot distributions\n", "plt.subplot(3, 3, 1)\n", "sns.histplot(df_metric_ls_ro['num_nodes'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of nodes')\n", "plt.xlabel('Number of nodes')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 2)\n", "sns.histplot(df_metric_ls_ro['num_edges'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of edges')\n", "plt.xlabel('Number of edges')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 3)\n", "sns.histplot(df_metric_ls_ro['diameter'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of diameter')\n", "plt.xlabel('Diameter')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 4)\n", "sns.histplot(df_metric_ls_ro['average_degree'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of average degree')\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", "plt.subplot(3, 3, 5)\n", "sns.histplot(df_metric_ls_ro['density'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(1e1, upper_limit)\n", "plt.title('Distribution of density')\n", "plt.xlabel('Density')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.subplot(3, 3, 6)\n", "sns.histplot(df_metric_ls_ro['connectivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of connectivity')\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", "plt.subplot(3, 3, 7)\n", "sns.histplot(df_metric_ls_ro['clustering'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of clustering')\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", "plt.subplot(3, 3, 8)\n", "sns.histplot(df_metric_ls_ro['degree_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of degree assortivity')\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", "plt.subplot(3, 3, 9)\n", "sns.histplot(df_metric_ls_ro['sentiment_assortivity'], bins=20)\n", "plt.yscale('log')\n", "plt.ylim(0.9, upper_limit)\n", "plt.title('Distribution of sentiment assortivity')\n", "plt.xlabel('Sentiment assortivity')\n", "plt.ylabel('Count')\n", "plt.grid()\n", "plt.tick_params(axis='both', direction='in',top=True, right=True)\n", "\n", "plt.suptitle(f'Metrics (nodes > 10, edges < 400) {casename} case', fontsize=16)\n", "plt.tight_layout(rect=[0, 0, 1, 0.99])\n", "\n", "plt.savefig(f'../datasets/{case}-metrics-ls-ro.png')\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 }