{"spec_id":"network-weighted","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' network-weighted: Weighted Network Graph with Edge Thickness\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 86/100 | Created: 2026-05-17\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(ragg)\n\nset.seed(42)\n\n# Theme tokens\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nIMPRINT   <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                 \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data: Trade network between countries (weighted by annual trade volume)\nset.seed(42)\nnodes <- data.frame(\n  id = 1:15,\n  country = c(\"USA\", \"China\", \"India\", \"Japan\", \"Germany\",\n              \"UK\", \"France\", \"Brazil\", \"Canada\", \"Mexico\",\n              \"South Korea\", \"Italy\", \"Spain\", \"Netherlands\", \"Australia\"),\n  region = c(\"Americas\", \"Asia\", \"Asia\", \"Asia\", \"Europe\",\n             \"Europe\", \"Europe\", \"Americas\", \"Americas\", \"Americas\",\n             \"Asia\", \"Europe\", \"Europe\", \"Europe\", \"Oceania\")\n)\n\n# Edges: trade relationships with weights (annual volume in billions USD)\nedges <- data.frame(\n  source = c(1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14),\n  target = c(2, 3, 4, 3, 5, 6, 4, 5, 5, 11, 12, 6, 7, 7, 14, 8, 9, 10, 9, 2, 13, 14, 1),\n  weight = c(640, 380, 285, 620, 290, 240, 185, 165, 310, 85, 150, 520, 380, 275, 220, 185, 95, 120, 85, 330, 95, 80, 65)\n)\n\n# Simple spring-like layout: place nodes on a circle with slight random jitter\nn_nodes <- nrow(nodes)\nangles <- seq(0, 2 * pi, length.out = n_nodes + 1)[1:n_nodes]\nnodes$x <- 2 * cos(angles) + rnorm(n_nodes, 0, 0.3)\nnodes$y <- 2 * sin(angles) + rnorm(n_nodes, 0, 0.3)\n\n# Create edge data frame with node positions\nedges_positioned <- edges %>%\n  left_join(nodes %>% select(id, x, y), by = c(\"source\" = \"id\")) %>%\n  rename(x_start = x, y_start = y) %>%\n  left_join(nodes %>% select(id, x, y), by = c(\"target\" = \"id\")) %>%\n  rename(x_end = x, y_end = y)\n\n# Normalize edge weights for linewidth (1 to 4)\nweight_min <- min(edges_positioned$weight)\nweight_max <- max(edges_positioned$weight)\nedges_positioned$linewidth <- 1 + 3 * (edges_positioned$weight - weight_min) / (weight_max - weight_min)\n\n# Create base theme\nanyplot_theme <- theme_minimal(base_size = 14) +\n  theme(\n    plot.background   = element_rect(fill = PAGE_BG, color = NA),\n    panel.background  = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid        = element_blank(),\n    axis.title        = element_blank(),\n    axis.text         = element_blank(),\n    axis.ticks        = element_blank(),\n    plot.title        = element_text(color = INK, size = 24, face = \"bold\"),\n    plot.margin       = margin(20, 20, 20, 20, \"pt\")\n  )\n\n# Create plot\np <- ggplot() +\n  # Draw edges first (so they appear behind nodes)\n  geom_segment(\n    data = edges_positioned,\n    aes(x = x_start, y = y_start, xend = x_end, yend = y_end, linewidth = linewidth),\n    color = IMPRINT[1],\n    alpha = 0.5,\n    lineend = \"round\"\n  ) +\n  # Draw nodes\n  geom_point(\n    data = nodes,\n    aes(x = x, y = y),\n    color = IMPRINT[1],\n    size = 8,\n    alpha = 0.9\n  ) +\n  # Node labels\n  geom_text(\n    data = nodes,\n    aes(x = x, y = y, label = substr(country, 1, 3)),\n    color = PAGE_BG,\n    size = 3.5,\n    fontface = \"bold\"\n  ) +\n  scale_linewidth(range = c(1, 4), guide = \"none\") +\n  coord_equal() +\n  labs(title = \"network-weighted · ggplot2 · anyplot.ai\") +\n  anyplot_theme\n\n# Save\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 16,\n  height   = 9,\n  units    = \"in\",\n  dpi      = 300\n)\n"}