Introduction

On Dave Mustaine’s birthday, this document presents a small tribute through network analysis. The idea is to study his position within a broad network of rock, metal, and related guitarists, constructed from musical collaborations and cover relationships.

The goal is not to determine who is the “best” guitarist. Centrality describes the structural position of each musician within the observed network and allows us to examine, from another perspective, how connected each guitarist is, how strongly they act as bridges, and how close they are to the rest of the network.

Data collection

The network was constructed from publicly available sources documenting relationships among rock and metal guitarists. The initial roster was assembled primarily from the Wikipedia List of heavy metal guitarists, while recorded collaborations were verified mainly through MusicBrainz, Discogs, and AllMusic. Cover relationships were cross-checked primarily using SecondHandSongs. Additional release-specific sources were used when necessary, including official or specialized pages for projects such as G3, Generation Axe, Hear ’n Aid, Rock Aid Armenia, and selected individual recordings. An undirected edge was created whenever reliable evidence indicated that two guitarists had recorded together or that one had performed or recorded a cover associated with the other. Multiple pieces of evidence for the same pair were aggregated into a single binary connection. Consequently, the network should be regarded as an evidence-based, non-exhaustive representation of documented musical relationships.

Main sources: MusicBrainz, SecondHandSongs, Discogs, AllMusic, and the Wikipedia List of heavy metal guitarists.

Data and packages

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)))

The database contains guitarists as vertices. Two guitarists are connected when there is at least one captured piece of evidence that they recorded together or that one performed a cover associated with the other. The network is binary, undirected, and symmetric.

Historical membership in the same band is not sufficient by itself to create an edge. In addition, the absence of an edge means that no evidence was captured for that pair, not necessarily that no musical relationship ever existed.

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())

The analyzed version contains 724 guitarists, 685 aggregated relationships, and 869 evidence records.

Network construction

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

network_summary <- tibble(
     measure = c(
          "Guitarists",
          "Connections",
          "Collaborations",
          "Covers"
     ),
     value = c(
          vcount(g),
          ecount(g),
          sum(E(g)$relation == "collaboration"),
          sum(E(g)$relation == "cover")
     )
)

knitr::kable(
     network_summary,
     col.names = c("Measure", "Value"),
     align = c("l", "r")
)
Measure Value
Guitarists 724
Connections 685
Collaborations 438
Covers 247

The full network includes isolated musicians and small disconnected groups. To compare centrality measures based on distances and paths, we work with the giant component.

Giant component

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(
          "Guitarists",
          "Connections"
     ),
     value = c(
          vcount(g_gc),
          ecount(g_gc)
     )
)

knitr::kable(
     giant_summary,
     col.names = c("Giant component", "Value"),
     align = c("l", "r")
)
Giant component Value
Guitarists 227
Connections 493

The giant component contains 227 guitarists connected through 493 relationships. This is the subset used to construct the global ranking.

Centrality measures

We consider five complementary centrality measures:

  • degree, which summarizes direct connectivity;
  • betweenness, which identifies musicians who act as bridges;
  • closeness, which measures accessibility to the rest of the network;
  • eigenvector centrality, which rewards connections to musicians who are themselves central;
  • PageRank, which summarizes structural importance through recursively relevant connections.
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
)

Each measure captures a different way of occupying a relevant position in the network. For this reason, the final ranking is not based on a single centrality measure.

Global centrality index

The original measures are on different scales, and some are partially redundant. To construct a more balanced index, we first transform each centrality measure into its percentile within the giant component.

We define three dimensions:

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

where \(L_i\) summarizes connectivity and structural importance, combining degree, eigenvector centrality, and PageRank;

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

where \(B_i\) represents brokerage; and

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

where \(C_i\) represents accessibility.

The global index is

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

Thus, the three dimensions receive equal weight and the index is expressed on a 0 to 100 scale.

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()
     )

This index favors guitarists who simultaneously combine relevant connections, the ability to link different parts of the network, and a globally accessible position.

Global top 10

top10_global <- centrality |>
     slice_head(n = 10) |>
     transmute(
          Rank = global_rank,
          Guitarist = guitarist,
          `Global index` = global_index,
          Connectivity = 100 * connectivity,
          Brokerage = 100 * brokerage,
          Accessibility = 100 * accessibility
     )

knitr::kable(
     top10_global,
     digits = 1,
     align = c("r", "l", "r", "r", "r", "r")
)
Rank Guitarist Global index Connectivity Brokerage Accessibility
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

The highest positions do not necessarily correspond to the guitarists with the largest number of direct connections. The ranking also rewards the ability to connect different regions of the network and to maintain a position that is close to the rest of the guitarists.

Dave Mustaine

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

dave_summary <- dave |>
     transmute(
          Rank = global_rank,
          Guitarist = guitarist,
          `Global index` = global_index,
          Connectivity = 100 * connectivity,
          Brokerage = 100 * brokerage,
          Accessibility = 100 * accessibility,
          Degree = degree
     )

knitr::kable(
     dave_summary,
     digits = 1,
     align = c("r", "l", "r", "r", "r", "r", "r")
)
Rank Guitarist Global index Connectivity Brokerage Accessibility Degree
7 Dave Mustaine 96.5 93.4 99.6 96.5 20

Dave Mustaine ranks 7 out of 227 in the global ranking, with a global centrality index of 96.5 out of 100.

His position does not depend only on the number of connections. He also stands out through his role as a bridge and through his location within the global structure of the network.

Visual ranking

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                          ~ "Others"
          )
     )

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",
               "Others" = "#C9CED6"
          )
     ) +
     scale_x_continuous(
          limits = c(
               0,
               max(top15_plot$global_index) * 1.08
          ),
          expand = expansion(
               mult = c(0, 0)
          )
     ) +
     labs(
          title = "Most central guitarists in the network",
          subtitle = "Global centrality index",
          x = "Global index",
          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

Mustaine’s position among the most central guitarists shows that his role in the network combines connectivity, brokerage, and accessibility, rather than depending on a single measure.

The network

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]

In the visualization, node size represents the global index. Guitarists in the top 10 are shown in gold, while Dave Mustaine is highlighted in red.

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 = "Collaboration",
               cover = "Cover"
          ),
          name = "Relationship"
     ) +

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

     labs(
          title = "Network of rock and metal guitarists",
          subtitle = paste0(
               "Giant component: ",
               vcount(g_gc),
               " guitarists and ",
               ecount(g_gc),
               " connections\n",
               "Gold: top 10 by global index | Red: Dave Mustaine"
          ),
          caption = paste0(
               "Global index = average of connectivity, ",
               "brokerage, and accessibility."
          )
     ) +

     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

The network shows something that a simple list of collaborations cannot reveal directly: some guitarists occupy positions that connect different scenes, generations, and musical communities. Dave Mustaine’s high global centrality is consistent with a career positioned across several relevant regions of this structure.

Final comment

This analysis offers a quantitative way to celebrate Dave Mustaine’s career: not simply by counting albums, bands, or songs, but by examining his position within a broader network of musical relationships.

The global index should be interpreted as a measure of structural centrality in this database, not as a definitive measure of artistic quality or historical influence. Even with that precaution, his position provides a clear visualization of the reach of his connections within the rock and metal universe.

Happy birthday, Dave Mustaine.