{"spec_id":"network-weighted","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nnetwork-weighted: Weighted Network Graph with Edge Thickness\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 70/100 | Updated: 2026-05-17\n\"\"\"\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nfrom matplotlib.collections import LineCollection\n\n\n# Set seaborn style for consistent aesthetics\nsns.set_style(\"whitegrid\")\nsns.set_context(\"talk\", font_scale=1.2)\n\n# Data: Trade network between countries (billions USD annual trade volume)\nnp.random.seed(42)\n\n# Define nodes (15 countries as trading partners)\ncountries = [\n    \"USA\",\n    \"China\",\n    \"Germany\",\n    \"Japan\",\n    \"UK\",\n    \"France\",\n    \"India\",\n    \"Brazil\",\n    \"Canada\",\n    \"Mexico\",\n    \"S. Korea\",\n    \"Italy\",\n    \"Australia\",\n    \"Spain\",\n    \"Netherlands\",\n]\nn_nodes = len(countries)\nnode_idx = {name: i for i, name in enumerate(countries)}\n\n# Create weighted edges (source, target, weight in billions USD)\nedges_data = [\n    (\"USA\", \"China\", 580),\n    (\"USA\", \"Canada\", 620),\n    (\"USA\", \"Mexico\", 550),\n    (\"USA\", \"Japan\", 210),\n    (\"USA\", \"Germany\", 180),\n    (\"USA\", \"UK\", 140),\n    (\"China\", \"Japan\", 320),\n    (\"China\", \"S. Korea\", 280),\n    (\"China\", \"Germany\", 190),\n    (\"China\", \"Australia\", 150),\n    (\"China\", \"India\", 90),\n    (\"Germany\", \"France\", 170),\n    (\"Germany\", \"Netherlands\", 200),\n    (\"Germany\", \"UK\", 130),\n    (\"Germany\", \"Italy\", 140),\n    (\"Japan\", \"S. Korea\", 85),\n    (\"Japan\", \"Australia\", 70),\n    (\"UK\", \"France\", 95),\n    (\"UK\", \"Netherlands\", 80),\n    (\"France\", \"Italy\", 85),\n    (\"France\", \"Spain\", 100),\n    (\"India\", \"USA\", 75),\n    (\"Brazil\", \"USA\", 65),\n    (\"Brazil\", \"China\", 100),\n    (\"Canada\", \"UK\", 25),\n    (\"Mexico\", \"Canada\", 20),\n    (\"Australia\", \"Japan\", 60),\n    (\"S. Korea\", \"USA\", 120),\n    (\"Netherlands\", \"UK\", 70),\n    (\"Italy\", \"Spain\", 50),\n]\n\n# Build edge list with indices\nedges = [(node_idx[s], node_idx[t], w) for s, t, w in edges_data]\n\n# Calculate weighted degree for node sizing\nweighted_degrees = np.zeros(n_nodes)\nfor i, j, w in edges:\n    weighted_degrees[i] += w\n    weighted_degrees[j] += w\n\n# Spring layout using Fruchterman-Reingold algorithm (inline implementation)\nnp.random.seed(42)\npos = np.random.rand(n_nodes, 2) * 2 - 1\narea = 4.0\nk_rep = np.sqrt(area / n_nodes) * 0.8\n\nfor iteration in range(300):\n    # Calculate repulsive forces between all pairs\n    disp = np.zeros((n_nodes, 2))\n    for i in range(n_nodes):\n        for j in range(i + 1, n_nodes):\n            delta = pos[i] - pos[j]\n            dist = max(np.linalg.norm(delta), 0.01)\n            force = k_rep**2 / dist\n            direction = delta / dist\n            disp[i] += direction * force\n            disp[j] -= direction * force\n\n    # Calculate attractive forces along edges\n    for i, j, w in edges:\n        delta = pos[i] - pos[j]\n        dist = max(np.linalg.norm(delta), 0.01)\n        force = dist**2 / k_rep * (1 + w / 300)\n        direction = delta / dist\n        disp[i] -= direction * force\n        disp[j] += direction * force\n\n    # Limit displacement and update positions\n    temp = 0.1 * (1 - iteration / 300)\n    for i in range(n_nodes):\n        disp_norm = max(np.linalg.norm(disp[i]), 0.01)\n        pos[i] += disp[i] / disp_norm * min(disp_norm, temp)\n        pos[i] = np.clip(pos[i], -1, 1)\n\n# Scale positions to canvas\npositions = pos * 0.8\n\n# Prepare edge data\nedge_weights = [w for _, _, w in edges]\nmin_weight, max_weight = min(edge_weights), max(edge_weights)\nedge_widths = [1 + (w - min_weight) / (max_weight - min_weight) * 11 for w in edge_weights]\nedge_colors_norm = [(w - min_weight) / (max_weight - min_weight) for w in edge_weights]\n\n# Scale node sizes based on weighted degree\nnode_sizes = (\n    400 + (weighted_degrees - weighted_degrees.min()) / (weighted_degrees.max() - weighted_degrees.min()) * 2200\n)\n\n# Create figure\nfig, ax = plt.subplots(figsize=(16, 9))\n\n# Create color palette for edges using seaborn\nedge_cmap = sns.color_palette(\"Blues\", as_cmap=True)\n\n# Draw edges as LineCollection for proper width variation\nsegments = []\ncolors = []\nwidths = []\nfor idx, (i, j, _w) in enumerate(edges):\n    segments.append([positions[i], positions[j]])\n    colors.append(edge_cmap(edge_colors_norm[idx]))\n    widths.append(edge_widths[idx])\n\nlc = LineCollection(segments, colors=colors, linewidths=widths, alpha=0.7, zorder=1)\nax.add_collection(lc)\n\n# Node colors using seaborn palette\nnode_palette = sns.color_palette(\"Set2\", n_colors=n_nodes)\n\n# Draw nodes\nax.scatter(positions[:, 0], positions[:, 1], s=node_sizes, c=node_palette, edgecolors=\"white\", linewidths=2.5, zorder=2)\n\n# Draw labels with offset to avoid overlap with nodes\nfor i, name in enumerate(countries):\n    ax.annotate(\n        name,\n        (positions[i, 0], positions[i, 1] + 0.06),\n        fontsize=13,\n        fontweight=\"bold\",\n        color=\"#333333\",\n        ha=\"center\",\n        va=\"bottom\",\n        zorder=3,\n    )\n\n# Add colorbar for edge weights\nsm = plt.cm.ScalarMappable(cmap=edge_cmap, norm=plt.Normalize(vmin=min_weight, vmax=max_weight))\nsm.set_array([])\ncbar = plt.colorbar(sm, ax=ax, shrink=0.6, pad=0.02)\ncbar.set_label(\"Trade Volume (Billions USD)\", fontsize=18)\ncbar.ax.tick_params(labelsize=14)\n\n# Add legend for node size interpretation\nlegend_elements = [\n    plt.scatter([], [], s=500, c=\"#66c2a5\", edgecolors=\"white\", linewidths=2, label=\"Lower total trade\"),\n    plt.scatter([], [], s=1400, c=\"#66c2a5\", edgecolors=\"white\", linewidths=2, label=\"Medium total trade\"),\n    plt.scatter([], [], s=2600, c=\"#66c2a5\", edgecolors=\"white\", linewidths=2, label=\"Higher total trade\"),\n]\nax.legend(\n    handles=legend_elements,\n    loc=\"upper left\",\n    fontsize=13,\n    title=\"Node Size = Total Trade\",\n    title_fontsize=15,\n    framealpha=0.9,\n)\n\n# Style\nax.set_title(\"International Trade Network · network-weighted · seaborn · pyplots.ai\", fontsize=24, pad=20)\nax.set_xlim(-1.1, 1.2)\nax.set_ylim(-1.1, 1.1)\nax.axis(\"off\")\nax.set_aspect(\"equal\")\n\nplt.tight_layout()\nplt.savefig(\"plot.png\", dpi=300, bbox_inches=\"tight\", facecolor=\"white\")\n"}