---
title: "MCU. Un análisis codificado"
description: |
Un recorrido por las películas y los personajes del Universo Cinematográfico de Marvel
author:
- name: Arantxa Anais Arcos Raimundo
affiliation: Universitat de València
affiliation-url: https://www.uv.es
date: 2026-01-02 #--
categories: [trabajo BigData, marvel, hérores, películas] #--
image: "./imagenes/universo_marvel.jpg"
title-block-banner: true #- {true, false, "green","#AA0000"}
title-block-banner-color: "EB1F48" #-"#FFFFFF"
toc-depth: 3
smooth-scroll: true
format:
html:
#backgroundcolor: "#F1F3F4"
#embed-resources: true
link-external-newwindow: true
#css: assets/my_css_file.css #- CUIDADO!!!!
code-tools: true
code-link: true
---
## Motivación
El Universo Cinematográfico de Marvel ha cambiado la industria del cine al popularizar el concepto de *multiverso* y *universo compartido*. No se trata solo de películas individuales, sino de una red interconectada de historias donde las acciones de una película afectan a las demás y todas estas están relacionadas.
Así pues, se ha convertido en una de las franquicias cinematográficas más taquillera de la historia, demostrando cómo una saga a largo plazo como lo es la *Saga del infinito* puede mantener el interés del público durante más de una década.
Por ello, el trabajo presente tiene el objetivo de entender y averiguar las distintas características de las películas y personajes de Marvel desde la perspectiva de una fan.
*Así que vamos allá!!*
## Historia del MCU
En primer lugar, debemos saber que el UCM es una franquicia de medios centrada en una serie de películas de superhéroes producidas por Marvel Studios, basada en los personajes de Marvel Comics. La saga se divide en fases con dos arcos grandes: la Saga del Infinito y la Saga del Multiverso.
Nos centramos en sobre todo en la *Saga del Infinito* ya que es dónde se encuentra el grupo de *Avengers* el cual estaremos analizando durante todo el trabajo. Cabe mencionar que la película que pone final a la lucha de los vengadores está en la fase tres y es *Avengers: Endgame* (2019).
Por otro lado, la primera película fue *Iron Man* en 2008 y fue dirigida por Jon Favreau. Esta película tiene mucha relevancia ya que fue el inicio de la presentación de héores individuales para posteriormente dar lugar a los Vengadores.
Así pues, en relación con *The Avengers* estos se reunen por primera vez en 2012, año de estreno de la película. El grupo original está formado por:
- Iron Man.
- Captain America.
- Thor.
- Hulk.
- Black Widow.
- Hawkeye.
Sin embargo, cabe mencionar que los personajes aparecidos en la última batalla y que, por tanto, vamos a considerar Vengadores y son los que vamos a analizar son los siguientes:
- Trinidad de Vengadores: Iron Man, Capitán América y Thor.
- Líderes de apoyo: Hulk, Hawkeye, War Machine, Ant-Man, Rocket y Nebula.
- Héroes regresados por portales: Spider-Man, Black Panther, Shuri, Okoye, Falcon, Winter Soldier, Scarlet Witch, Doctor Strange, Wong y Wasp.
- Guardianes de la Galaxia: Star-Lord, Drax, Mantis, Groot y Gamora (2014).
- Refuerzos clave: Capitana Marvel, Valkyrie, Korg, Miek y Rescue (Pepper Potts).
- Ejércitos aliados: Las Dora Milaje de Wakanda, los Hechiceros de las Artes Místicas, el ejército de Asgard y los Saqueadores.
- Especial mención a Black Widow.
## Introducción
Vamos a utilizar datos extraídos de Kaggle, los cuales podemos encontrar [aquí](https://www.kaggle.com/datasets/jainaru/marvel-movies-box-office-data?resource=download), [aquí](https://www.kaggle.com/datasets/sahirmaharajj/the-avengers-dataset/data),
[aquí](https://www.kaggle.com/datasets/dalepeh/mcu-movies-dataset) y
[aquí](https://www.kaggle.com/datasets/jonbown/marvel-screen-time),
A continuación, explicaremos un poco nuestra elección de datos:
Por un lado, encontramos dfs en los que solo tenemos las películas del MCU y sus distintas variables con las que realizaremos el trabajo como son: las fases, la recaudación, las valoraciones, los años de estreno, los directores ... Además, tenemos un df con la duración en minutos de las películas.
Por otro lado, hemos cargado dfs con los personajes tanto del MCU como de los cómics para poder trabajar con el global y solo con los Vengadores.
Los datos se pueden cargar en la memoria de de R/RStudio de esta forma:
```{r}
#Importación de películas
my_ruta <- "./data/marvel_movies.csv"
df_movies <- rio::import(my_ruta)
names (df_movies)
my_ruta_fases <- "./data/box_office.csv"
df_fases <- rio::import(my_ruta_fases)
my_ruta_duracion <- "./data/movie_times.csv"
df_duracion <- rio::import(my_ruta_duracion)
#- A continuación, para obtener los datos sobre los personajes podemos hacerlo de dos formas:
my_ruta_personajes <- "./data/avengers.csv" #- En este caso, creamos ruta relativa e importamos
df_personajes <- rio::import(my_ruta_personajes)
#install.packages("fivethirtyeight") ---- En este otro, instalamos el paquete que contiene a los personajes
#library(fivethirtyeight)
#df_personajes <- avengers ---- asociamos el nombre que queremos.install.packages("fivethirtyeight")
my_ruta_fases <- "./data/box_office.csv"
df_fases <- rio::import(my_ruta_fases)
my_ruta_total_personajes <- "./data/marvel_wikia_data.csv"
df_total_personajes <- rio::import(my_ruta_total_personajes)
```
El primer dataset contiene observaciones sobre un conjunto de `r nrow(df_movies)` películas de Marvel. Hay `r ncol(df_movies)` variables. El segundo dataset contiente observaciones sobre un conjunto `r nrow(df_personajes)` personajes de cómics. Hay `r ncol(df_personajes)` variables.
Cabe destacar que los datasets escogidos solo llegan hasta 2023 por lo que el análisis no incluirá los cambios que han habido de vengadores o algunas de las nuevas incorporaciones más recientes ni tendrá todas las películas de la fase 5 ni 6 (actual).
---
## Marvel Studios
A continuación, podemos observar una imagen en la que se encuentran muchos de los principales personajes del Universo Cinematográfico de Marvel.
```{r}
#| echo: false
my_url <- "https://images.alphacoders.com/100/1003204.jpg"
```

```{r}
#| echo: false
library(tidyverse)
library(ggimage)
library(magick)
#| label: animacion-heroes
#| message: false
#| warning: false
iron_man <- image_read("./imagenes/iron_man.jpg") %>% image_scale("700")
thor <- image_read("./imagenes/thor.webp") %>% image_scale("700")
black_panther <- image_read("./imagenes/black_panther.jpg") %>% image_scale("700")
hawkeye <- image_read("./imagenes/hawkeye.jpg") %>% image_scale("700")
black_widow <- image_read("./imagenes/black_widow.jpg") %>% image_scale("700")
spiderman <- image_read("./imagenes/spiderman.jpg") %>% image_scale("700")
captain_america <- image_read("./imagenes/capi.jpg") %>% image_scale("700")
hulk <- image_read("./imagenes/hulk.jpg") %>% image_scale("700")
dr_strange <- image_read("./imagenes/dr_strange.jpg") %>% image_scale("700")
guardianes <- image_read("./imagenes/guardianes.webp") %>% image_scale("700")
heroes <- c(iron_man, thor, black_panther, hawkeye, black_widow, spiderman, captain_america, hulk, dr_strange, guardianes)
animacion <- image_animate(heroes, fps = 0.5)
animacion
```
------------------------------------------------------------------------
Como bien sabemos el MCU es mucho más extenso ya que en los cómics hay muchos más personajes de los que han llegado a salir en la saga de *Avengers*; por ello, en el margen vamos a poner una foto con muchos más héroes y heroínas:
::: column-margin
{fig-align="center"}
:::
------------------------------------------------------------------------
## Algunos gráficos
Bueno pues vamos a hacer algún gráfico, pero claro antes he de cargar los paquetes.
```{r}
#| eval: true
library(tidyverse)
library(dplyr)
library(forcats)
library(gt)
library(plotly)
library(ggplot2)
library(dplyr)
library(stringr)
library (treemap) #install.packages ("treemap")
library(ggimage)
```
Por otro lado, vamos a establecer la paleta que pondremos en nuestros gráficos.
```{r setup}
#Configuración de paleta
library(paletteer)
paleta_discreta <- paletteer_c( "ggthemes::Orange-Blue-White Diverging", 6)
scale_fill_default <- function(...) {
scale_fill_gradientn(colors = mi_paleta, ...)
}
scale_color_default <- function(...) {
scale_color_gradientn(colors = mi_paleta, ...)
}
```
Un paso previo también es arreglar los datos. Para ello, en primer lugar, vamos a quitar aquellas columnas que no necesitamos o añadir las que nos hagan falta.
```{r}
#- En el df de películas no vamos a quitar ninguna columna; sin embargo, vamos a añadir una con el protagonista de cada película.
df_movies <- df_movies %>%
mutate (protagonista = case_when(
grepl("Iron", movie) ~ "Iron Man",
grepl("America", movie) ~ "Captain America",
grepl("Thor", movie) ~ "Thor",
grepl("Incredible Hulk", movie) ~ "Hulk",
grepl("Widow", movie) ~ "Black Widow",
grepl("Ant-Man", movie) ~ "Ant-Man",
grepl("Spider-Man", movie) ~ "Spider-Man",
grepl("Shang-Chi", movie) ~ "Shang-Chi",
grepl("Deadpool", movie) ~ "Deadpool",
grepl("Panther", movie) ~ "Black Panther",
grepl("Strange", movie) ~ "Dr Strange",
)) %>%
relocate (protagonista, .after = category)
#- En este caso, vamos a juntar el df de duración con el dde fases; para ello, primeramente tenemos que cambiar algunos nombres de películas porque la forma en la que están escritos es diferente en cada df y no podemos juntarlos bien.
df_duracion <- df_duracion %>%
mutate(movie = case_when(
movie == "Spider-Man: Far from Home" ~ "Spider-Man: Far From Home",
movie == "Shang-Chi" ~ "Shang-Chi and the Legend of the Ten Rings",
TRUE ~ movie))
df_fases <- df_fases %>%
select (Phase, Film, Year_Release, Director, movie_image) %>%
left_join (df_duracion, by = c("Film" = "movie")) #- Tener en cuenta que en df_duración solo hasta 2021, aparecerán 5 NAs.
#- Por otra parte, en el df de personajes vamos a hacer algunas modificaciones. Comenzaremos quitando estas dos columnas que no nos hacen falta:
df_personajes <- df_personajes %>%
select (- V22, - Notes)
#- A continuación, añadimos una nueva columna llamada "Alias" en las que pondremos los nombres de superhéroe de cada personaje y la recolocaremos al lado de los Nombres/Alias originales:
df_personajes <- df_personajes %>%
filter(`Name/Alias` != "Tony Masters") %>%
mutate(Alias = case_when(
grepl("Tony", `Name/Alias`) ~ "Iron Man",
grepl("Clinton Francis Barton", `Name/Alias`) ~ "Hawkeye",
grepl("Rogers", `Name/Alias`) ~ "Captain America",
grepl("Thor", `Name/Alias`) ~ "Thor",
grepl("Banner", `Name/Alias`) ~ "Hulk",
grepl("Romanova", `Name/Alias`) ~ "Black Widow",
grepl("Scott Edward Harris Lang", `Name/Alias`) ~ "Ant-Man",
grepl("Wanda Maximoff", `Name/Alias`) ~ "Scarlet Witch",
grepl("Peter Benjamin Parker", `Name/Alias`) ~ "Spider-Man",
grepl("Shang-Chi", `Name/Alias`) ~ "Shang-Chi",
grepl("T'Challa", `Name/Alias`) ~ "Black Panther",
grepl("Buchanan", `Name/Alias`) ~ "Bucky",
grepl("Victor Shade ", `Name/Alias`) ~ "Vision",
grepl("Doctor Stephen Vincent Strange", `Name/Alias`) ~ "Dr Strange",
TRUE ~ "Other")) %>%
relocate(Alias, .after = `Name/Alias`)
#- También vamos a crear un nuevo df con los Vengadores para poder juntarlos con el df_movies
avengers <- df_personajes %>%
filter (Alias != "Other") %>%
select (URL, `Name/Alias`, Alias, Appearances, Gender)
#- Finalmente, juntaremos el df de avengers con el de películas para tener observar las películas individuales que tienen algunos personajes:
pelicula_propia <- avengers %>%
left_join(df_movies, by = c("Alias" = "protagonista")) %>%
select (`Name/Alias`,movie, Gender, Appearances, Alias, year)
#- Finalmente, los df que usaremos son los siguientes:
#- df_fases
#- pelicula_propia
#- df_movies
#- df_total_personajes
```
------------------------------------------------------------------------
### Primeros gráficos. Comparativa numérica
En este apartado, realizamos una comparación entre el número de héroes y heroínas y la cantidad de películas que están asociadas a cada uno.
En este primer gráfico, vamos a contrastar el número de personajes que hay en el MCU según su género para mostrar en una gráfica que el número de hombres es mayor al de mujeres, debido a que en un comienzo la mayoría de personajes que se escribían eran hombres.
```{r}
#- primer gráfico
sexo <- df_total_personajes %>%
filter(SEX %in% c("Male Characters", "Female Characters"))
p <- ggplot(data = sexo,
mapping = aes(x = SEX, fill = SEX)) +
geom_bar() +
labs(
title = "Comparativa de sexo entre superhéroes",
x = "Sexo",
y = "Número de superhéroes") +
theme_minimal(base_family = "mono") +
theme(legend.position = "none",
plot.title = element_text(size=15,
vjust=2,
face="bold")) +
scale_fill_manual(values = paleta_discreta)
p
```
Tras esta imagen, vamos a comparar el porcentaje de películas individuales que tienen los hombres vs las mujeres dentro del equipo de Vengadores en un piechart. Como podemos comprobar, al haber más héroes, tanto en el equipo de Avengers como en general, el porcentaje de películas que van a estar protagonizadas por ellos es mucho mayor.
```{r}
porcentaje <- pelicula_propia %>%
filter(!is.na(movie)) %>%
count(Gender) %>%
mutate(
porcentaje = n / sum(n),
label = scales::percent(porcentaje, accuracy = 1))
p <- ggplot( porcentaje,
aes(x = "", y = n, fill = Gender)) +
geom_bar(stat = "identity", width = 1) +
coord_polar("y") +
geom_text(
aes(label = label),
position = position_stack(vjust = 0.5),
color = "white",
size = 5) +
theme_void(base_family = "mono")+
theme(plot.title = element_text(size=15,
vjust=2,
face="bold")) +
labs(
title = "Porcentaje de películas por género",
subtitle = "(protagonistas vengadores)") +
scale_fill_manual(values = paleta_discreta)
p
```
Por último, en la siguiente gráfica se muestra el número de películas que tiene cada uno de los Vengadores. Cabe destacar el caso de Spider-Man el cual realmente tendría más películas; sin embargo, en este análisis solo usamos las más recientes que son las 3 protagonizadas por el actor Tom Holland y la de animación con Miles Morales.
```{r}
p <- ggplot(pelicula_propia %>% filter(!is.na(movie)), aes(x = Alias)) +
geom_bar(fill = "#ff721a") +
labs(
title = "Número de películas por personaje",
x = "Personajes",
y = "Número de películas") +
coord_flip() +
geom_bar(aes(forcats::fct_rev(forcats::fct_infreq(Alias))),
fill = "#ff721a") +
theme_minimal(base_family = "mono")+
theme (plot.title = element_text(size=15,
vjust=2,
face="bold"))
p
```
------------------------------------------------------------------------
### Segundo gráfico. Marvel y la taquilla
A continuación, vamos a construir un gráfico circular para ver qué películas han tenido una mayor recaudación.
```{r}
#- segundo gráfico
recaudacion <- df_movies %>%
select(movie, `worldwide gross ($m)`) %>%
filter(!is.na(`worldwide gross ($m)`)) %>%
mutate(
id = row_number(),
value = `worldwide gross ($m)`,
individual = movie)
number_of_bar <- nrow(recaudacion)
angle <- 90 - 360 * (recaudacion$id - 0.5) / number_of_bar
recaudacion$hjust <- ifelse(angle < -90, 1, 0)
recaudacion$angle <- ifelse(angle < -90, angle + 180, angle)
p <- ggplot(recaudacion, aes(x = as.factor(id), y = value)) +
geom_bar(stat = "identity", fill = alpha("#2B5C8A", 0.9)) +
ylim(-max(recaudacion$value) * 0.25, max(recaudacion$value) * 1.1) +
theme_minimal(base_family = "mono") +
theme(
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(1, 4), "cm")) +
coord_polar(start = 0) +
geom_text(
data = recaudacion,
aes(
x = id,
y = value + max(recaudacion$value) * 0.05,
label = individual,
hjust = hjust),
angle = recaudacion$angle,
inherit.aes = FALSE,
size = 3,
alpha = 0.7)
p
```
A este gráfico, para hacer una mayor aproximación,lo acompañaremos con una tabla que muestre el top 5 películas más recaudadas.
```{r}
top5recaudacion <- df_movies %>%
arrange(desc(`worldwide gross ($m)`)) %>%
slice_head(n = 5) %>%
rename(recaudacion_taquilla = `worldwide gross ($m)`) %>%
select(movie, recaudacion_taquilla)
top5rec_tabla<- top5recaudacion %>%
gt() %>%
tab_header(
title = "Top 5 películas Marvel - Recaudación mundial",
subtitle = "(en millones de dólares)") %>%
cols_label(
movie = "Película",
recaudacion_taquilla = "Recaudación")%>%
fmt_currency(
columns = recaudacion_taquilla,
currency = "USD",
decimals = 0) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_body()) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_title(groups = c("title", "subtitle"))) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_column_labels()) %>%
tab_options(
table.background.color = "#FFF6ED")
top5rec_tabla
```
Finalmente, compararemos el top 5 películas más valoradas por la audiencia con las más valoradas por los críticos.
```{r}
top5audiencia <- df_movies %>%
arrange(desc(`audience % score`)) %>%
slice_head(n = 5) %>%
rename(audiencia = `audience % score`) %>%
select(movie, audiencia)
top5aud_tabla<- top5audiencia %>%
gt() %>%
tab_header(
title = "Top 5 películas Marvel - Mejor valoradas por la audiencia",
subtitle = "(en porcentaje)") %>%
cols_label(
movie = "Película",
audiencia = "Porcentaje") %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_body()) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_title(groups = c("title", "subtitle"))) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_column_labels()) %>%
tab_options(
table.background.color = "#FFF6ED")
top5aud_tabla
```
```{r}
top5criticos <- df_movies %>%
arrange(desc(`critics % score`)) %>%
slice_head(n = 5) %>%
rename(criticos = `critics % score`) %>%
select(movie, criticos)
top5crit_tabla<- top5criticos %>%
gt() %>%
tab_header(
title = "Top 5 películas Marvel - Mejor valoradas por los críticos",
subtitle = "(en porcentaje)") %>%
cols_label(
movie = "Película",
criticos = "Porcentaje") %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_body()) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_title(groups = c("title", "subtitle"))) %>%
tab_style(
style = cell_text(font = "mono"),
locations = cells_column_labels()) %>%
tab_options(
table.background.color = "#FFF6ED")
top5crit_tabla
```
Con esta comparación podemos observar que las películas más aclamadas por la audiencia no coinciden con la valoración de los críticos a excepción de las dos películas de Spider-man lo cual, desde mi punto de vista, es un acierto puesto que a nivel de producción y trama son muy buenos largometrajes.
------------------------------------------------------------------------
### Otro gráfico. Apariciones en cómics y películas.
Este gráfico muestra el número de apariciones que han tenido los personajes. En este caso, hemos pedido los cinco con mayor frecuencia entre los cuales encontramos a Spider-Man y el Capitán América.
```{r}
#- tercer gráfico
apariciones <- df_personajes %>%
mutate(Appearances = as.numeric(Appearances),
Appearances = if_else(`Name/Alias` == "_Jr._(Earth-616)#", 0, Appearances))
p <- apariciones %>%
filter (Appearances >= 2000) %>%
slice_max(Appearances, n = 5) %>%
ggplot( aes(`Name/Alias`, Appearances, size = 2.5, color = `Name/Alias`)) +
geom_point() +
theme_gray(base_family = "mono") +
theme(legend.position = "none",
plot.title = element_text(size=15,
vjust=2,
face="bold")) +
scale_color_manual(values = paleta_discreta) +
labs(
title = "Apariciones de personajes (aprox.)")
ggplotly(p)
```
------------------------------------------------------------------------
### ¿Cuál es la película más larga? ¿A qué fase pertenece?
En este apartado veremos las distintas duraciones que tienen las películas del MCU y qué fase es la que más películas tiene.
Además, obtendremos cuál es la película más larga.
```{r}
df_treemap <- df_fases %>%
filter(!is.na(runtime_min)) %>% # quitamos NAs
mutate(
runtime_min = as.numeric(str_extract(runtime_min, "^\\d+")))
treemap(
df_treemap,
index = c("Phase", "Film"),
vSize = "runtime_min",
vColor = "runtime_min",
type = "value",
palette = "RdYlBu",
fontsize.labels = c(16, 11),
fontcolor.labels = c("white", "black")
)
```
Como podemos observar, *Avengers: Endgame* es la más larga y pertenece a la fase 3.
------------------------------------------------------------------------
### Cartelera
Finalmente, acabaremos este trabajo mostrando un gráfico en el que se muestre el número de películas que se han estrenado en los diferentes años.
```{r}
df_plotline <- df_fases %>%
group_by(release_year) %>%
summarise(
n_peliculas = n(),
peliculas = paste(Film, collapse = "\n")) %>%
ungroup() %>%
mutate(release_year = as.numeric(release_year))
# Gráfico con línea y puntos
p <- ggplot(df_plotline, aes(x = release_year, y = n_peliculas,
text = paste0("Año: ", release_year,
"<br>Películas:\n", peliculas))) +
geom_line(aes(group = 1), color = "#8c0018" , size = 1) +
geom_point(color = "#720014" , size = 4) +
theme_minimal(base_family = "mono") +
xlab("Año de estreno") +
ylab("Cantidad de películas") +
theme(
panel.grid.minor = element_blank(),
panel.grid.major.x = element_blank())
# Convertir a interactivo
ggplotly(p, tooltip = "text")
```
---
<br>
Con esto acabo mi trabajo para BigData ;)
(**wakanda forever**)
<br>
------------------------------------------------------------------------
<br>
### Información sobre la sesión
Abajo muestro mi entorno de trabajo y paquetes utilizados
```{r}
#| echo: false
sessioninfo::session_info() %>%
details::details(summary = 'current session info')
```