Introducción

En el cumpleaños de Dave Mustaine, este documento presenta un pequeño homenaje desde el análisis de redes. La idea es estudiar su posición dentro de una red amplia de guitarristas de rock, metal y géneros relacionados, construida a partir de colaboraciones musicales y relaciones de cover.

El objetivo no es definir quién es el “mejor” guitarrista. La centralidad describe la posición estructural de cada músico dentro de la red observada y permite estudiar, desde otra perspectiva, qué tan conectado está, qué papel desempeña como puente y qué tan cerca se encuentra del resto de la red.

Datos y paquetes

suppressMessages(suppressWarnings(library(readxl)))
suppressMessages(suppressWarnings(library(dplyr)))
suppressMessages(suppressWarnings(library(igraph)))
suppressMessages(suppressWarnings(library(ggplot2)))
suppressMessages(suppressWarnings(library(ggraph)))
suppressMessages(suppressWarnings(library(graphlayouts)))
suppressMessages(suppressWarnings(library(ggrepel)))
suppressMessages(suppressWarnings(library(knitr)))

La base contiene guitarristas como vértices. Dos guitarristas están conectados cuando existe al menos una evidencia capturada de que grabaron juntos o de que uno interpretó un cover asociado al otro. La red es binaria, no dirigida y simétrica.

Pertenecer históricamente a la misma banda no es suficiente para crear una conexión. Además, la ausencia de una arista indica que no se capturó evidencia para esa pareja, no que necesariamente nunca haya existido una relación musical.

file_xlsx <- "rock_metal_guitarists_network_expanded.xlsx"

vertices <- read_excel(
     file_xlsx,
     sheet = "Vertices"
)

edges <- read_excel(
     file_xlsx,
     sheet = "Edges_Aggregated"
)

evidence <- read_excel(
     file_xlsx,
     sheet = "Relations_Evidence"
)

vertices_g <- vertices |>
     select(guitarist, everything()) |>
     rename(name = guitarist)

edges_g <- edges |>
     select(u, v, everything())

La versión analizada contiene 724 guitarristas, 685 relaciones agregadas y 869 registros de evidencia.

Construcción de la red

g <- graph_from_data_frame(
     d = edges_g,
     directed = FALSE,
     vertices = vertices_g
)

network_summary <- tibble(
     measure = c(
          "Guitarristas",
          "Conexiones",
          "Colaboraciones",
          "Covers"
     ),
     value = c(
          vcount(g),
          ecount(g),
          sum(E(g)$relation == "collaboration"),
          sum(E(g)$relation == "cover")
     )
)

knitr::kable(
     network_summary,
     col.names = c("Medida", "Valor"),
     align = c("l", "r")
)
Medida Valor
Guitarristas 724
Conexiones 685
Colaboraciones 438
Covers 247

La red completa incluye músicos aislados y pequeños grupos desconectados. Para comparar centralidades basadas en distancias y caminos, trabajamos con la componente gigante.

Componente gigante

comp <- components(g)

giant_id <- which.max(
     comp$csize
)

g_gc <- induced_subgraph(
     g,
     vids = V(g)[comp$membership == giant_id]
)

giant_summary <- tibble(
     measure = c(
          "Guitarristas",
          "Conexiones"
     ),
     value = c(
          vcount(g_gc),
          ecount(g_gc)
     )
)

knitr::kable(
     giant_summary,
     col.names = c("Componente gigante", "Valor"),
     align = c("l", "r")
)
Componente gigante Valor
Guitarristas 227
Conexiones 493

La componente gigante reúne 227 guitarristas conectados mediante 493 relaciones. Este es el subconjunto utilizado para construir el ranking global.

Medidas de centralidad

Consideramos cinco medidas complementarias:

  • grado, que resume conectividad directa;
  • intermediación, que identifica músicos que actúan como puentes;
  • cercanía, que mide accesibilidad al resto de la red;
  • centralidad de autovector, que valora conexiones con músicos también centrales;
  • PageRank, que resume importancia estructural mediante conexiones recursivamente relevantes.
degree_raw <- degree(
     g_gc,
     mode = "all"
)

degree_norm <- degree_raw / (vcount(g_gc) - 1)

betweenness_cent <- betweenness(
     g_gc,
     directed = FALSE,
     normalized = TRUE
)

closeness_cent <- closeness(
     g_gc,
     mode = "all",
     normalized = TRUE
)

eigenvector_cent <- eigen_centrality(
     g_gc,
     directed = FALSE,
     scale = TRUE
)$vector

pagerank_cent <- page_rank(
     g_gc,
     directed = FALSE,
     damping = 0.85
)$vector

centrality <- tibble(
     guitarist = V(g_gc)$name,
     degree = degree_raw,
     degree_centrality = degree_norm,
     betweenness = betweenness_cent,
     closeness = closeness_cent,
     eigenvector = eigenvector_cent,
     pagerank = pagerank_cent
)

Cada medida captura una forma distinta de ocupar una posición relevante. Por eso no utilizamos una sola centralidad para definir el ranking final.

Índice global de centralidad

Las medidas originales están en escalas distintas y algunas son parcialmente redundantes. Para construir un índice más equilibrado, primero transformamos cada centralidad a su percentil dentro de la componente gigante.

Definimos tres dimensiones:

\[ L_i = \frac{ P_{i,D} + P_{i,E} + P_{i,P} }{3}, \]

donde \(L_i\) resume conectividad e importancia, combinando grado, autovector y PageRank;

\[ B_i = P_{i,B}, \]

donde \(B_i\) representa intermediación; y

\[ C_i = P_{i,C}, \]

donde \(C_i\) representa accesibilidad.

El índice global es

\[ I_i = 100 \left( \frac{ L_i + B_i + C_i }{3} \right). \]

Así, las tres dimensiones reciben el mismo peso y el índice queda expresado en una escala de 0 a 100.

centrality <- centrality |>
     mutate(
          pct_degree = percent_rank(degree_centrality),
          pct_betweenness = percent_rank(betweenness),
          pct_closeness = percent_rank(closeness),
          pct_eigenvector = percent_rank(eigenvector),
          pct_pagerank = percent_rank(pagerank),

          connectivity = (
               pct_degree +
               pct_eigenvector +
               pct_pagerank
          ) / 3,

          brokerage = pct_betweenness,

          accessibility = pct_closeness,

          global_index = 100 * (
               connectivity +
               brokerage +
               accessibility
          ) / 3
     ) |>
     arrange(
          desc(global_index),
          guitarist
     ) |>
     mutate(
          global_rank = row_number()
     )

Este índice favorece a quienes combinan conexiones relevantes, capacidad de articular distintas zonas de la red y una posición globalmente accesible.

Top 10 global

top10_global <- centrality |>
     slice_head(n = 10) |>
     transmute(
          Posición = global_rank,
          Guitarrista = guitarist,
          `Índice global` = global_index,
          Conectividad = 100 * connectivity,
          Intermediación = 100 * brokerage,
          Accesibilidad = 100 * accessibility
     )

knitr::kable(
     top10_global,
     digits = 1,
     align = c("r", "l", "r", "r", "r", "r")
)
Posición Guitarrista Índice global Conectividad Intermediación Accesibilidad
1 Dave Murray 99.8 99.4 100.0 100.0
2 James Hetfield 98.7 97.9 98.7 99.6
3 Kirk Hammett 97.5 97.5 96.0 99.1
4 Vivian Campbell 97.1 98.5 95.1 97.8
5 Adrian Smith 97.1 98.4 94.2 98.7
6 Scott Gorham 97.0 94.0 99.1 97.8
7 Dave Mustaine 96.5 93.4 99.6 96.5
8 Yngwie Malmsteen 95.1 96.3 92.9 96.0
9 Mick Mars 95.0 96.5 91.6 96.9
10 Scott Ian 94.4 92.2 97.8 93.4

Los primeros lugares no corresponden necesariamente a quienes tienen más conexiones directas. El ranking también recompensa la capacidad de conectar partes diferentes de la red y mantener una posición cercana al resto de los guitarristas.

Dave Mustaine

dave <- centrality |>
     filter(
          guitarist == "Dave Mustaine"
     )

dave_summary <- dave |>
     transmute(
          Posición = global_rank,
          Guitarrista = guitarist,
          `Índice global` = global_index,
          Conectividad = 100 * connectivity,
          Intermediación = 100 * brokerage,
          Accesibilidad = 100 * accessibility,
          Grado = degree
     )

knitr::kable(
     dave_summary,
     digits = 1,
     align = c("r", "l", "r", "r", "r", "r", "r")
)
Posición Guitarrista Índice global Conectividad Intermediación Accesibilidad Grado
7 Dave Mustaine 96.5 93.4 99.6 96.5 20

Dave Mustaine ocupa el puesto 7 de 227 en el ranking global, con un índice de 96.5 sobre 100.

Su posición no depende únicamente del número de conexiones. También destaca por su papel como puente y por su ubicación dentro de la estructura global de la red.

Ranking visual

top15_plot <- centrality |>
     slice_head(n = 15) |>
     mutate(
          guitarist = factor(
               guitarist,
               levels = rev(guitarist)
          ),
          group = case_when(
               guitarist == "Dave Mustaine" ~ "Dave Mustaine",
               global_rank <= 10             ~ "Top 10",
               TRUE                          ~ "Otros"
          )
     )

p_rank <- ggplot(
     top15_plot,
     aes(
          x = global_index,
          y = guitarist,
          fill = group
     )
) +
     geom_col(
          width = 0.72
     ) +
     geom_text(
          aes(
               label = sprintf("%.1f", global_index)
          ),
          hjust = -0.15,
          size = 3.6
     ) +
     scale_fill_manual(
          values = c(
               "Dave Mustaine" = "#B2182B",
               "Top 10" = "#E3B341",
               "Otros" = "#C9CED6"
          )
     ) +
     scale_x_continuous(
          limits = c(
               0,
               max(top15_plot$global_index) * 1.08
          ),
          expand = expansion(
               mult = c(0, 0)
          )
     ) +
     labs(
          title = "Guitarristas más centrales de la red",
          subtitle = "Índice global de centralidad",
          x = "Índice global",
          y = NULL,
          fill = NULL
     ) +
     theme_minimal(
          base_size = 12
     ) +
     theme(
          plot.title = element_text(
               size = 18,
               face = "bold"
          ),
          plot.subtitle = element_text(
               size = 12,
               colour = "#4B5563"
          ),
          panel.grid.major.y = element_blank(),
          panel.grid.minor = element_blank(),
          legend.position = "bottom"
     )

p_rank

La posición de Mustaine entre los guitarristas más centrales muestra que su presencia en la red combina conectividad, intermediación y accesibilidad, en lugar de depender de una única medida.

La red

idx <- match(
     V(g_gc)$name,
     centrality$guitarist
)

V(g_gc)$degree_cent <- centrality$degree_centrality[idx]
V(g_gc)$betweenness_cent <- centrality$betweenness[idx]
V(g_gc)$closeness_cent <- centrality$closeness[idx]
V(g_gc)$eigenvector_cent <- centrality$eigenvector[idx]
V(g_gc)$pagerank_cent <- centrality$pagerank[idx]

V(g_gc)$connectivity <- centrality$connectivity[idx]
V(g_gc)$brokerage <- centrality$brokerage[idx]
V(g_gc)$accessibility <- centrality$accessibility[idx]

V(g_gc)$global_index <- centrality$global_index[idx]
V(g_gc)$global_rank <- centrality$global_rank[idx]

En la visualización, el tamaño de cada nodo representa el índice global. Los guitarristas del top 10 aparecen en dorado y Dave Mustaine se destaca en rojo.

set.seed(1702)

p_network <- ggraph(
     g_gc,
     layout = "stress"
) +

     geom_edge_link(
          aes(
               colour = relation
          ),
          alpha = 0.18,
          linewidth = 0.45,
          show.legend = TRUE
     ) +

     geom_node_point(
          aes(
               size = global_index
          ),
          shape = 21,
          fill = "#C9CED6",
          colour = "white",
          stroke = 0.25,
          alpha = 0.90
     ) +

     geom_node_point(
          data = function(x) {
               x |>
                    filter(
                         global_rank <= 10,
                         name != "Dave Mustaine"
                    )
          },
          aes(
               size = global_index
          ),
          shape = 21,
          fill = "#E3B341",
          colour = "#715500",
          stroke = 1.1
     ) +

     geom_node_point(
          data = function(x) {
               x |>
                    filter(
                         name == "Dave Mustaine"
                    )
          },
          aes(
               size = global_index
          ),
          shape = 21,
          fill = "#B2182B",
          colour = "#570812",
          stroke = 1.6
     ) +

     geom_node_text(
          data = function(x) {
               x |>
                    filter(
                         global_rank <= 10,
                         name != "Dave Mustaine"
                    )
          },
          aes(
               label = name
          ),
          repel = TRUE,
          size = 3.6,
          fontface = "bold",
          colour = "#20242A",
          box.padding = 0.5,
          point.padding = 0.4,
          max.overlaps = Inf
     ) +

     geom_node_label(
          data = function(x) {
               x |>
                    filter(
                         name == "Dave Mustaine"
                    )
          },
          aes(
               label = name
          ),
          repel = TRUE,
          size = 4.3,
          fontface = "bold",
          fill = "#B2182B",
          colour = "white",
          label.size = 0,
          label.padding = unit(
               0.35,
               "lines"
          ),
          box.padding = 0.8,
          point.padding = 0.7
     ) +

     scale_edge_colour_manual(
          values = c(
               collaboration = "#697B8C",
               cover = "#C28A44"
          ),
          labels = c(
               collaboration = "Colaboración",
               cover = "Cover"
          ),
          name = "Relación"
     ) +

     scale_size_continuous(
          range = c(
               2.0,
               9.0
          ),
          limits = c(
               0,
               100
          ),
          guide = "none"
     ) +

     labs(
          title = "Red de guitarristas de rock y metal",
          subtitle = paste0(
               "Componente gigante: ",
               vcount(g_gc),
               " guitarristas y ",
               ecount(g_gc),
               " conexiones\n",
               "Dorado: top 10 según índice global | Rojo: Dave Mustaine"
          ),
          caption = paste0(
               "Índice global = promedio de conectividad, ",
               "intermediación y accesibilidad."
          )
     ) +

     guides(
          edge_colour = guide_legend(
               override.aes = list(
                    alpha = 0.8,
                    linewidth = 1.5
               )
          )
     ) +

     theme_graph(
          base_family = "sans"
     ) +

     theme(
          plot.title = element_text(
               size = 22,
               face = "bold",
               colour = "#15191E"
          ),
          plot.subtitle = element_text(
               size = 12,
               colour = "#4B5563",
               lineheight = 1.15
          ),
          plot.caption = element_text(
               size = 9,
               colour = "#6B7280"
          ),
          legend.position = "bottom",
          legend.title = element_text(
               face = "bold"
          ),
          plot.margin = margin(
               20,
               25,
               20,
               25
          )
     )

p_network

La red permite ver algo que una lista de colaboraciones no muestra directamente: algunos guitarristas ocupan posiciones que conectan escenas, generaciones y comunidades musicales diferentes. La alta centralidad global de Dave Mustaine es consistente con una trayectoria situada en múltiples zonas relevantes de esta estructura.

Comentario final

Este análisis ofrece una manera cuantitativa de celebrar la trayectoria de Dave Mustaine: no contando únicamente discos, bandas o canciones, sino observando su posición dentro de una red más amplia de relaciones musicales.

El índice global debe interpretarse como una medida de centralidad estructural en esta base de datos, no como una medida definitiva de calidad artística o influencia histórica. Aun con esa precaución, su posición permite visualizar de forma clara el alcance de sus conexiones dentro del universo del rock y el metal.

Happy birthday, Dave Mustaine.