Introducción

Este proyecto analiza dos frentes de la industria de Medios y Entretenimiento - el catálogo de títulos de Netflix 2023 y el catálogo de películas de IMDb de 2026

Para cada uno de estas fuentes de datos, se planean realizar una serie de análisis cuantitativos desde entre ellos covarianza, distribuciones de probabilidad, pruebas de hipótesis, χ2, t de Student y regresión simple.

Parte Fuente de datos Enfoque del análisis
I — Series (Netflix) Kaggle - Netflix 2023 Horas vistas, valoraciones, calificación y disponibilidad global
II — Películas (IMDb) Vega - IMDb 2023 Calificación IMDb, año de estreno, género y tendencias temporales

Parte I — Análisis de Netflix

ruta_netflix <- "Fuentes/total_netflix_2023 new.csv"
netflix <- read.csv(ruta_netflix, stringsAsFactors = FALSE)

netflix <- netflix %>%
  mutate(
    Hours.Viewed = as.numeric(gsub("[^0-9.]", "", Hours.Viewed)),
    Number.of.Ratings = as.numeric(gsub("[^0-9.]", "", Number.of.Ratings)),
    Rating = as.numeric(Rating),
    log_Hours = log10(Hours.Viewed),
    Available.Globally. = factor(Available.Globally., levels = c("No", "Yes")),
    GenreSimple = case_when(
      grepl("Comedy", Genre) ~ "Comedy",
      grepl("Drama", Genre) ~ "Drama",
      grepl("Action", Genre) ~ "Action",
      TRUE ~ "Otro"
    ),
    GenreSimple = factor(GenreSimple)
  ) %>%
  filter(
    !is.na(Hours.Viewed),
    !is.na(Rating),
    !is.na(Number.of.Ratings),
    Hours.Viewed > 0,
    Number.of.Ratings >= 0
  )

n_netflix <- nrow(netflix)

De Kaggle hemos sacado el set de datos de Netflix, un servicio de streaming de series y películas, que se enfoca en mostrar lo que la gente ha visto a lo largo de 6 meses que incluye casi el 99% de lo visto durante el periodo.

El set de datos cuenta con 9 variables y 14,633 observaciones de títulos despues de la limpieza donde se filtraron observaciones donde no había valores en todas las columnas.

Para cada Serie de Netflix se tienen datos como: - Nombre de la serie - Disponibilidad global - Fecha de lanzamiento - Horas vista - Etc.


1. Análisis de covarianza (Netflix)

Contexto

Deseamos saber si las horas vistas (horas totales que un show se ha visto), número de valoraciones (gente que le da calificaciones) y calificación (calificación total del 0–10) varían juntas. Utilizaremos la correlación de Pearson para estimar una relación lineal.

Hemos calculado el logaritmo de las horas vistas debido al sesgo presente en esta variable (muchas series se ven muy pocas horas, mientras que otras muy exitosas son vistas mucho más).

vars_cov <- netflix %>%
  select(log_Hours, Number.of.Ratings, Rating) %>%
  rename(
    `log10(Horas vistas)` = log_Hours,
    `N. valoraciones` = Number.of.Ratings,
    Calificacion = Rating
  )

cor_mat <- cor(vars_cov, use = "complete.obs")

tabla_netflix(
  as.data.frame(round(cor_mat, 3)),
  caption = "Netflix — Matriz de correlación",
  align = "c",
  digits = 3
)
Netflix — Matriz de correlación
log10(Horas vistas) N. valoraciones Calificacion
log10(Horas vistas) 1.000 -0.003 -0.008
N. valoraciones -0.003 1.000 0.117
Calificacion -0.008 0.117 1.000
cor_largo <- as.data.frame(as.table(cor_mat))
names(cor_largo) <- c("Var1", "Var2", "r")

ggplot(cor_largo, aes(Var1, Var2, fill = r)) +
  geom_tile(color = "white", linewidth = 0.8) +
  geom_text(aes(label = sprintf("%.2f", r)), color = "#3D3D3D", fontface = "bold", size = 5) +
  scale_fill_gradientn(colours = paleta_cor_nf, limits = c(-1, 1), name = "Correlación") +
  labs(
    title = titulo_grafica("Análisis de covarianza"),
    subtitle = "Correlación entre log10(horas), valoraciones y calificación",
    x = NULL, y = NULL
  ) +
  tema_netflix +
  theme(axis.text.x = element_text(angle = 25, hjust = 1, face = "bold"))
Netflix: matriz de correlación.

Netflix: matriz de correlación.

Conclusión

La correlación más fuerte aparece entre N. valoraciones y Calificacion (0.117). Entre log-horas y calificación la relación es débil (-0.008): más horas vistas no garantizan mejor calificación en esta muestra.


2. Distribución de probabilidades (Netflix)

Contexto

Analizaremos si las calificaciones siguen una distribución normal. Sobrepondremos la curva normal teórica a la gráfica de barras como referencia visual.

mu_n <- mean(netflix$Rating)
sd_n <- sd(netflix$Rating)

tabla_netflix(
  data.frame(
    Estadistico = c("Media", "Desv. est.", "Mínimo", "Máximo"),
    Valor = c(mu_n, sd_n, min(netflix$Rating), max(netflix$Rating))
  ),
  digits = 3,
  caption = "Netflix — Resumen de calificaciones",
  align = c("l", "r")
)
Netflix — Resumen de calificaciones
Estadistico Valor
Media 6.624
Desv. est. 1.256
Mínimo 1.400
Máximo 10.000
x_seq <- seq(min(netflix$Rating), max(netflix$Rating), length.out = 200)
curva_norm <- data.frame(Rating = x_seq, densidad = dnorm(x_seq, mu_n, sd_n))

ggplot(netflix, aes(x = Rating, fill = GenreSimple)) +
  geom_histogram(aes(y = after_stat(density)), bins = 25, alpha = 0.75, color = "white", position = "identity") +
  geom_line(data = curva_norm, aes(x = Rating, y = densidad), inherit.aes = FALSE, color = nf_rojo, linewidth = 1.4) +
  scale_fill_manual(values = col_genero_nf, name = "Género") +
  labs(
    title = titulo_grafica("Distribución de probabilidades"),
    subtitle = "Histograma por género con curva normal teórica superpuesta",
    x = "Calificación (0–10)", y = "Densidad"
  ) +
  tema_netflix +
  theme(legend.position = "bottom")
Netflix: distribución de calificaciones.

Netflix: distribución de calificaciones.

Conclusión

Las calificaciones se concentran cerca de 6.62 con desviación estándard de 1.26. El análisis visual muestra que las calificaciones parecen estar distribuidas normalmente, pero es necesario un análisis más riguros para asegurarlo.


3. Prueba de hipótesis y t de Student (Netflix)

Contexto

Queremos ver si las horas vistas entre series disponibles globalmente son diferentes frente a las que no lo son, para esto haremos una prueba visual con gráficos de caja y bigotes y la prueba t de Student (\(H_0\): medias iguales).

t_prueba <- t.test(log_Hours ~ Available.Globally., data = netflix, var.equal = FALSE)

tabla_netflix(
  data.frame(
    Estadistico = c("t", "gl", "valor-p", "Media log10 (No)", "Media log10 (Yes)"),
    Valor = c(
      round(t_prueba$statistic, 4),
      round(t_prueba$parameter, 2),
      format.pval(t_prueba$p.value, digits = 4),
      round(t_prueba$estimate[1], 3),
      round(t_prueba$estimate[2], 3)
    )
  ),
  caption = "Netflix — Prueba t de Student",
  align = c("l", "r")
)
Netflix — Prueba t de Student
Estadistico Valor
t t -12.5488
df gl 7683.76
valor-p < 2.2e-16
mean in group No Media log10 (No) 6.381
mean in group Yes Media log10 (Yes) 6.553
ggplot(netflix, aes(x = Available.Globally., y = log_Hours, fill = Available.Globally.)) +
  geom_boxplot(alpha = 0.75, width = 0.55, color = nf_negro, outlier.color = nf_rojo2) +
  geom_jitter(aes(color = Available.Globally.), width = 0.15, alpha = 0.25, size = 0.6) +
  stat_summary(fun = mean, geom = "point", shape = 18, size = 3.5, color = nf_negro) +
  scale_fill_manual(values = col_global_nf, guide = "none") +
  scale_color_manual(values = col_global_nf, guide = "none") +
  labs(
    title = titulo_grafica("Prueba t de Student"),
    subtitle = "Boxplots lado a lado; rombo negro = media muestral",
    x = "Disponible globalmente",
    y = expression(log[10](Horas~vistas))
  ) +
  annotate("text", x = 1.5, y = max(netflix$log_Hours) * 0.98, color = nf_rojo,
           label = paste0("valor-p = ", format.pval(t_prueba$p.value, digits = 3))) +
  tema_netflix
Netflix: boxplots lado a lado (log10 horas).

Netflix: boxplots lado a lado (log10 horas).

Conclusión

Con un valor-p muy chico (menor a 2.2e-16) rechazamos la hipotesis nula a favor de la alterna - la disponibilidad global se asocia con mayor audiencia.


4. Prueba Chi-cuadrado (Netflix)

Contexto

Queremos saber si hay una correlación entre el hecho de que una serie tenga disponibilidad global y el género (Acción, Comedia, Drama, etc.). Por ejemplo la comedia es muy personal de cada país por lo que puede no ser redituable disponibilizarla globalmente. Para esto usaremos la \(\chi^2\) de Pearson.

tab_chi <- table(netflix$Available.Globally., netflix$GenreSimple)
dimnames(tab_chi) <- list(Disponibilidad = c("No", "Yes"), Genero = levels(netflix$GenreSimple))

tabla_chi_df <- data.frame(
  Disponibilidad = rownames(tab_chi),
  as.data.frame.matrix(tab_chi),
  check.names = FALSE
)
names(tabla_chi_df)[-1] <- colnames(tab_chi)

tabla_netflix(
  tabla_chi_df,
  caption = "Netflix — Tabla de contingencia",
  align = c("l", rep("r", ncol(tab_chi)))
)
Netflix — Tabla de contingencia
Disponibilidad Action Comedy Drama Otro
No No 853 3493 2618 3420
Yes Yes 342 1442 1104 1361
chi_resultado <- chisq.test(tab_chi)

tabla_netflix(
  data.frame(
    `Chi-cuadrado` = round(chi_resultado$statistic, 3),
    gl = chi_resultado$parameter,
    `valor-p` = format.pval(chi_resultado$p.value, digits = 4),
    check.names = FALSE
  ),
  caption = "Netflix — Resultado Chi-cuadrado",
  align = c("l", "r", "r", "r")
)
Netflix — Resultado Chi-cuadrado
Chi-cuadrado gl valor-p
X-squared 1.64 3 0.6504

Conclusión

Con una \(\chi^2\) de 1.64, por arriba del valor p (0.05), decidimos no rechazar la hipótesis nula - no hay una asociación entre la disponibilidad global y el género.


5. Análisis de regresión (Netflix)

Contexto

Queremos realizar un análisis de regreción entre la calificación y las horas vistas, así tendremos un modelo para predecir que califiación tendría una series si supieramos cuantas horas vistas tiene. Una vez más, tomaremos el logaritmo de las horas vistas.

mod_n <- lm(Rating ~ log_Hours, data = netflix)
coef_n <- as.data.frame(summary(mod_n)$coefficients)
coef_n$Termino <- rownames(coef_n)
rownames(coef_n) <- NULL

tabla_netflix(
  coef_n[, c("Termino", "Estimate", "Std. Error", "Pr(>|t|)")],
  digits = 6, caption = "Netflix — Regresión simple",
  align = c("l", "r", "r", "r")
)
Netflix — Regresión simple
Termino Estimate Std. Error Pr(>|t|)
(Intercept) 6.708467 0.090008 0.000000
log_Hours -0.013170 0.013903 0.343518
tabla_netflix(
  data.frame(
    Metrica = c("R²", "R² ajustado"),
    Valor = c(summary(mod_n)$r.squared, summary(mod_n)$adj.r.squared)
  ),
  digits = 4, caption = "Netflix — Bondad de ajuste",
  align = c("l", "r")
)
Netflix — Bondad de ajuste
Metrica Valor
1e-04
R² ajustado 0e+00
ggplot(netflix, aes(x = log_Hours, y = Rating, color = GenreSimple)) +
  geom_point(alpha = 0.35, size = 1.2) +
  geom_smooth(aes(group = 1), method = "lm", se = TRUE, color = nf_rojo, fill = "#FAE8E8", linewidth = 1.2) +
  scale_color_manual(values = col_genero_nf, name = "Género") +
  labs(
    title = titulo_grafica("Análisis de regresión"),
    subtitle = "Modelo lineal: calificación ~ log10(horas vistas)",
    x = expression(log[10](Horas~vistas)), y = "Calificación"
  ) +
  tema_netflix +
  theme(legend.position = "bottom")
Netflix: regresión calificación ~ log10(horas).

Netflix: regresión calificación ~ log10(horas).

Conclusión

Nuestro modelo de regresión no parece explicar la calificación inspeccionandolo visualmente ni utilizando la \(R^2\).


Parte II — Análisis de películas (IMDb)

El IMDb es la base de datos en línea más grande y popular del mundo sobre cine, televisión, streaming y videojuegos. Propiedad de Amazon, es utilizada por millones de usuarios para consultar el reparto , equipo de producción, biografías, sinópsis, curiosidades y calificaciones de cualquier obra audiovisual.

El set de datos cuenta con 16 variables y 3201 observaciones despues de la limpieza donde se filtraron observaciones donde no había valores en todas las columnas.

Para cada película se tienen datos como: - Título - Las ganancias en taquilla en Estados Unidos y Globalmente - El presupuesto - La fecha de lanzamiento - Las calificaciones en las plataformas de Rotten Tomatoes y IMDb - Etc.

ruta_imdb <- "Fuentes/movies.json"
peliculas <- as.data.frame(fromJSON(ruta_imdb))

peliculas <- peliculas %>%
  mutate(
    `Release Date` = as.Date(`Release Date`, format = "%b %d %Y"),
    Year = as.numeric(format(`Release Date`, "%Y")),
    Rating = `IMDB Rating`,
    Decade = floor(Year / 10) * 10,
    Worldwide.Gross = as.numeric(gsub("[^0-9.]", "", as.character(`Worldwide Gross`))),
    Major.Genre = as.factor(`Major Genre`)
  ) %>%
  filter(!is.na(Rating), !is.na(Year))

n_peliculas <- nrow(peliculas)
top15 <- peliculas %>% arrange(desc(Rating)) %>% head(15)

peliculas_genero <- peliculas %>%
  filter(!is.na(Major.Genre)) %>%
  add_count(Major.Genre, name = "n_genero") %>%
  filter(n_genero >= 50) %>%
  mutate(Major.Genre = droplevels(Major.Genre))

resumen_genero <- peliculas_genero %>%
  group_by(Major.Genre) %>%
  summarise(
    Peliculas = n(),
    Promedio = mean(Rating, na.rm = TRUE),
    Mediana = median(Rating, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(desc(Promedio))

generos_facet <- levels(peliculas_genero$Major.Genre)

decade_genero <- peliculas %>%
  filter(Major.Genre %in% generos_facet, !is.na(Decade), Decade >= 1920) %>%
  group_by(Major.Genre, Decade) %>%
  summarise(
    Promedio = mean(Rating, na.rm = TRUE),
    Peliculas = n(),
    .groups = "drop"
  ) %>%
  filter(Peliculas >= 5)

1. Top 15 películas (IMDb)

Contexto

Identificamos las 15 películas con mejor calificación acorde al IMDb partiendo de la base de datos mencionada. Este gráfico de barras resume el extremo superior de la distribución y facilita comparar títulos destacados por su califiación.

ggplot(top15, aes(x = reorder(Title, Rating), y = Rating, fill = Rating)) +
  geom_col(show.legend = FALSE) +
  scale_fill_gradient(low = "#8C7A00", high = imdb_amarillo) +
  coord_flip() +
  labs(
    title = titulo_grafica("Top 15 películas mejor calificadas", "IMDb"),
    subtitle = "Barras ordenadas por calificación IMDb",
    x = NULL, y = "Calificación IMDb"
  ) +
  tema_imdb
Películas (IMDb): Top 15 por calificación.

Películas (IMDb): Top 15 por calificación.

Conclusión

El tope del ranking supera 8.8 puntos; las mejores películas concentran calificaciones muy altas entre público y crítica, lo que refleja la selección positiva típica de catálogos curados o muy valorados por usuarios.


2. Distribución de probabilidades (IMDb)

Contexto

El histograma muestra cómo se reparten las calificaciones IMDb en la base de datos anteriormente mencionada. Superponemos la curva normal teórica (media y desviación muestrales) para compararlas, igual que en las series de Netflix.

mu_p <- mean(peliculas$Rating)
sd_p <- sd(peliculas$Rating)

tabla_imdb(
  data.frame(
    Estadistico = c("Media", "Desv. est.", "Mínimo", "Máximo"),
    Valor = c(mu_p, sd_p, min(peliculas$Rating), max(peliculas$Rating))
  ),
  digits = 3,
  caption = "IMDb — Resumen de calificaciones",
  align = c("l", "r")
)
IMDb — Resumen de calificaciones
Estadistico Valor
Media 6.283
Desv. est. 1.252
Mínimo 1.400
Máximo 9.200
x_seq_p <- seq(min(peliculas$Rating), max(peliculas$Rating), length.out = 200)
curva_norm_p <- data.frame(Rating = x_seq_p, densidad = dnorm(x_seq_p, mu_p, sd_p))

ggplot(peliculas, aes(x = Rating)) +
  geom_histogram(aes(y = after_stat(density)), binwidth = 0.2, fill = imdb_amarillo, color = "white", alpha = 0.85) +
  geom_line(data = curva_norm_p, aes(x = Rating, y = densidad), inherit.aes = FALSE, color = imdb_azul_osc, linewidth = 1.4) +
  labs(
    title = titulo_grafica("Distribución de probabilidades", "IMDb"),
    subtitle = "Histograma con curva normal teórica superpuesta",
    x = "Calificación IMDb", y = "Densidad"
  ) +
  tema_imdb
Películas (IMDb): histograma de calificaciones con curva normal.

Películas (IMDb): histograma de calificaciones con curva normal.

Conclusión

Las calificaciones se concentran cerca de 6.28 (DE = 1.25). La mayoría de películas supera 6.0 puntos; la curva normal es referencia visual, no prueba formal de normalidad.


3. Calificación por género — Prueba de hipótesis (IMDb)

Contexto

¿La calificación IMDb depende del género principal? Agrupamos los géneros con al menos 50 películas y comparamos sus distribuciones con gráficos de caja y bigote lado a lado. Además aplicamos el análisis de varianza ANOVA, debido a que estamos haciendo la comparativa entre género (cada una integrada por cantidades diferentes de películas) y calificaciones. La hipotesis nula, \(H_0\) indica que el promedio de la calificación es igual entre géneros.

tabla_imdb(
  resumen_genero,
  digits = 3,
  caption = "IMDb — Calificación promedio por género (mínimo 50 películas)",
  align = c("l", "r", "r", "r")
)
IMDb — Calificación promedio por género (mínimo 50 películas)
Major.Genre Peliculas Promedio Mediana
Drama 738 6.773 6.90
Musical 50 6.448 6.85
Thriller/Suspense 233 6.361 6.40
Adventure 251 6.345 6.40
Action 392 6.115 6.20
Romantic Comedy 130 5.873 5.85
Comedy 635 5.854 6.00
Horror 209 5.676 5.60
anova_genero_p <- aov(Rating ~ Major.Genre, data = peliculas_genero)
anova_tabla_p <- as.data.frame(summary(anova_genero_p)[[1]])
anova_tabla_p$Fuente <- rownames(anova_tabla_p)
rownames(anova_tabla_p) <- NULL

tabla_imdb(
  anova_tabla_p[, c("Fuente", "Df", "Sum Sq", "Mean Sq", "F value", "Pr(>F)")],
  digits = 4,
  caption = "IMDb — ANOVA: calificación por género",
  align = c("l", "r", "r", "r", "r", "r"),
  na = ""
)
IMDb — ANOVA: calificación por género
Fuente Df Sum Sq Mean Sq F value Pr(>F)
Major.Genre 7 403.1377 57.5911 40.9151 0
Residuals 2630 3701.9285 1.4076 NA NA
genero_orden <- resumen_genero %>% arrange(Promedio) %>% pull(Major.Genre)

ggplot(peliculas_genero, aes(x = reorder(Major.Genre, Rating, FUN = median), y = Rating, fill = Major.Genre)) +
  geom_boxplot(alpha = 0.75, width = 0.65, color = imdb_azul_osc, outlier.color = imdb_amarillo) +
  geom_jitter(width = 0.12, alpha = 0.15, size = 0.5, color = imdb_gris_med) +
  stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = imdb_negro) +
  scale_fill_manual(values = paleta_genero_imdb, guide = "none") +
  scale_x_discrete(limits = genero_orden) +
  labs(
    title = titulo_grafica("Calificación por género cinematográfico", "IMDb"),
    subtitle = "Géneros con ≥ 50 películas; rombo negro = media",
    x = "Género principal", y = "Calificación IMDb"
  ) +
  tema_imdb +
  theme(axis.text.x = element_text(angle = 30, hjust = 1))
Películas (IMDb): calificación por género principal.

Películas (IMDb): calificación por género principal.

Conclusión

El género con mayor promedio es Drama (6.77); el menor, Horror (5.68). La prueba ANOVA nos da un valor-p de <2e-16 por lo que “rechazamos \(H_0\). el género sí se asocia con diferencias en calificación (por ejemplo comedia vs. terror), aunque el gráfico muestra matices y no es tan categórica la diferencia para establecer una norma debido.


4. Evolución del promedio por década (IMDb)

Contexto

Comparamos cómo cambia la calificación promedio por década de estreno dentro de cada género principal (con al menos 5 películas por década). El panel de gráficas con facet_wrap permite ver si la tendencia temporal es similar en drama, comedia, acción y otros géneros.

ggplot(decade_genero, aes(x = Decade, y = Promedio)) +
  geom_line(color = imdb_amarillo2, linewidth = 1) +
  geom_point(color = imdb_amarillo, size = 2) +
  facet_wrap(~Major.Genre, scales = "free_y", ncol = 3) +
  labs(
    title = titulo_grafica("Evolución de la calificación por década", "IMDb"),
    subtitle = "Un panel por género principal (mínimo 5 películas por década)",
    x = "Década de estreno", y = "Calificación promedio"
  ) +
  tema_imdb +
  theme(strip.text = element_text(face = "bold", color = imdb_amarillo2))
Películas (IMDb): evolución por década según género.

Películas (IMDb): evolución por década según género.

Conclusión

No todas las décadas ni todos los géneros evolucionan igual: algunos paneles muestran ligero hasta muy drásticos ascenso o descensos según la época, mientras otros se mantienen estables. Esto indica que las décadas y más específicamente los años interactúan con el género.


5. Análisis de regresión (IMDb)

Contexto

¿Las películas más recientes reciben mejores o peores calificaciones? Ajustamos una regresión lineal simple (año → calificación).

mod_p <- lm(Rating ~ Year, data = peliculas)
coef_p <- as.data.frame(summary(mod_p)$coefficients)
coef_p$Termino <- rownames(coef_p)
rownames(coef_p) <- NULL

tabla_imdb(
  coef_p[, c("Termino", "Estimate", "Std. Error", "Pr(>|t|)")],
  digits = 6, caption = "IMDb — Regresión calificación ~ año",
  align = c("l", "r", "r", "r")
)
IMDb — Regresión calificación ~ año
Termino Estimate Std. Error Pr(>|t|)
(Intercept) 27.642287 3.828858 0
Year -0.010689 0.001916 0
cor_ano <- cor(peliculas$Year, peliculas$Rating, use = "complete.obs")
ggplot(peliculas, aes(x = Year, y = Rating)) +
  geom_point(color = imdb_amarillo2, alpha = 0.35, size = 1) +
  geom_smooth(method = "lm", se = TRUE, color = imdb_azul_osc, fill = "#FDF8DC", linewidth = 1.1) +
  labs(
    title = titulo_grafica("Análisis de regresión", "IMDb"),
    subtitle = "Modelo lineal: calificación ~ año de estreno",
    x = "Año de estreno", y = "Calificación IMDb"
  ) +
  tema_imdb
Películas (IMDb): año de estreno vs. calificación con recta de regresión.

Películas (IMDb): año de estreno vs. calificación con recta de regresión.

Conclusión

Correlación año–calificación: -0.102; \(R^2\) = 0.0103. La pendiente es significativa pero el modelo explica poca variación: el año de estreno por sí solo no determina la calificación IMDb en este conjunto amplio. Si bien, con la gráfica anterior podemos inferir que ciertos géneros son más favorecidos en ciertas décadas, no es una norma.


6. Nube de palabras — Títulos (IMDb)

Contexto

La nube de palabras resume las palabras más frecuentes en los títulos de las películas, se eliminaron muletillas, artículos, y preposiciones para obtener sustantivos y nombres relevantes.

if (requireNamespace("wordcloud", quietly = TRUE) &&
    requireNamespace("tm", quietly = TRUE)) {
  library(wordcloud)
  library(tm)

  palabras_vacias <- unique(c(
    stopwords("english"),
    stopwords("spanish"),
    "movie", "film", "story",
    "part", "chapter", "vs", "ii", "iii", "iv", "v", "vi",
    "the", "and", "of", "in", "to", "a", "an", "for", "on", "at", "by",
    "de", "la", "el", "los", "las", "y", "en", "un", "una", "del", "al"
  ))

  corpus_titulos <- Corpus(VectorSource(peliculas$Title))
  corpus_titulos <- tm_map(corpus_titulos, content_transformer(tolower))
  corpus_titulos <- tm_map(corpus_titulos, removePunctuation)
  corpus_titulos <- tm_map(corpus_titulos, removeNumbers)
  corpus_titulos <- tm_map(corpus_titulos, removeWords, palabras_vacias)
  corpus_titulos <- tm_map(corpus_titulos, stripWhitespace)

  tdm <- TermDocumentMatrix(corpus_titulos)
  m <- as.matrix(tdm)
  freq <- sort(rowSums(m), decreasing = TRUE)
  freq <- freq[nchar(names(freq)) > 2]

  par(bg = "white", fg = imdb_azul_osc, mar = rep(0.5, 4))
  wordcloud(
    words = names(freq),
    freq = freq,
    random.order = FALSE,
    colors = c(imdb_negro, imdb_gris_med, imdb_azul_osc, imdb_amarillo2, imdb_amarillo, "#D4A800"),
    max.words = 80,
    scale = c(3, 0.5)
  )
} else {
  plot.new()
  text(0.5, 0.5, "Instale los paquetes wordcloud y tm para ver esta figura")
}
Películas (IMDb): nube de palabras sin muletillas.

Películas (IMDb): nube de palabras sin muletillas.

Conclusión

Del análisis emergen términos con significado narrativo o temático (nombres, lugares, conceptos). La nube refleja la diversidad del catálogo y no debe leerse como ranking de películas, sino como exploración del lenguaje usado en los títulos. Se destaca que el impacto de la industria Norteamericana ha sido una marca considerable en los títulos de las películas.