Recursos/Librerías

CONTENIDO

1. Contextualización:

La base de datos “Movies Box Office Dataset (2000-2024)” es un conjunto de datos abierto, extraído de Kaggle y publicado por Aditya Jilla, recoge información detallada sobre el rendimiento de taquilla de películas estrenadas entre los años 2000 y 2024. Este dataset permite analizar tendencias en la industria cinematográfica, identificar patrones en la recaudación y evaluar el impacto de diversos factores en el éxito de una película. Incluye variables clave como el título de la película, el año de lanzamiento, el género, la recaudación tanto a nivel doméstico como internacional, el presupuesto de producción, la calificación de la audiencia, el país de origen y el idioma principal. Al proporcionar datos sobre la taquilla a nivel mundial, este conjunto de datos es ideal para estudios comparativos entre películas, géneros y períodos de tiempo, permitiendo analizar cómo han evolucionado las preferencias del público y qué características están asociadas con un mayor éxito comercial.

2. Objetivo del análisis/estudio

  • Analizar los factores que influyen en el éxito financiero de las películas en taquilla, evaluando cómo variables como el género, el año de lanzamiento, la calificación del público y el país de origen afectan la recaudación tanto a nivel doméstico como internacional.
  • Identificar tendencias en la industria cinematográfica entre 2000 y 2024, comparando el rendimiento de diferentes tipos de películas y explorando qué características están asociadas con una mayor rentabilidad.

Además, se llevará a cabo una revisión exhaustiva de los valores faltantes, se detectarán y tratarán outliers, y se aplicarán técnicas de limpieza de datos, todo con el fin de preparar adecuadamente el conjunto de datos, con el fin de asegurar que la calidad del conjunto de datos sea adecuada para un análisis oportuno y eficiente.

3. Carga y Estructura del Dataset

Para garantizar la correcta lectura de la base de datos en R, se utilizó la función read.csv(), la cual permite cargar archivos en formato CSV de manera eficiente. Se implementó file.choose() para facilitar la selección del archivo sin necesidad de especificar manualmente la ruta. Además, se estableció fileEncoding = “UTF-8” para evitar problemas con caracteres especiales y header = TRUE para asegurar que la primera fila se interprete como los nombres de las columnas. Esta configuración permite manipular los datos sin inconvenientes y facilita el análisis exploratorio.

# Cargar la base de datos en la variable "datos"
datos <- read.csv(file.choose(), 
        sep=",", 
        header=TRUE, 
        fileEncoding = "UTF-8")

# Inspección de la estructura del dataset
library(kableExtra)
kable(datos[1:20, ], caption= "Tabla 1: DataSet ") %>%
  kable_styling(full_width = F) %>%
  column_spec(2, width = "20em") %>%
  scroll_box(width = "900px", height = "450px")
Tabla 1: DataSet
Rank Release.Group X.Worldwide X.Domestic Domestic.. X.Foreign Foreign.. Year Genres Rating Vote_Count Original_Language Production_Countries
1 Mission: Impossible II 546388108 215409889 39.4 330978219 60.6 2000 Adventure, Action, Thriller 6.126/10 6741 en United States of America
2 Gladiator 460583960 187705427 40.8 272878533 59.2 2000 Action, Drama, Adventure 8.217/10 19032 en United Kingdom, United States of America
3 Cast Away 429632142 233632142 54.4 196000000 45.6 2000 Adventure, Drama 7.663/10 11403 en United States of America
4 What Women Want 374111707 182811707 48.9 191300000 51.1 2000 Comedy, Romance 6.45/10 3944 en United Kingdom, United States of America
5 Dinosaur 349822765 137748063 39.4 212074702 60.6 2000 Animation, Family, Adventure 6.544/10 2530 en United States of America
6 How the Grinch Stole Christmas 345842198 260745620 75.4 85096578 24.6 2000 Family, Comedy, Fantasy 6.8/10 7591 en Germany, United States of America
7 Meet the Parents 330444045 166244045 50.3 164200000 49.7 2000 Comedy, Romance 6.675/10 5916 en United States of America
8 The Perfect Storm 328718434 182618434 55.6 146100000 44.4 2000 Action, Adventure, Drama, Thriller 6.466/10 2312 en United States of America
9 X-Men 296339528 157299718 53.1 139039810 46.9 2000 Adventure, Action, Science Fiction 7.005/10 11355 en United States of America
10 What Lies Beneath 291420351 155464351 53.3 135956000 46.7 2000 Drama, Horror, Mystery, Thriller 6.416/10 1818 en United States of America
11 Scary Movie 278019771 157019771 56.5 121000000 43.5 2000 Comedy 6.364/10 6984 en United States of America
12 Charlie’s Angels 264105545 125305545 47.4 138800000 52.6 2000 Action, Adventure, Comedy, Crime, Thriller 5.836/10 4148 en United States of America
13 Erin Brockovich 256271286 125595205 49.0 130676081 51.0 2000 Drama 7.4/10 3198 en United States of America
14 Unbreakable 248118121 95011339 38.3 153106782 61.7 2000 Thriller, Drama, Mystery 7.143/10 9281 en United States of America
15 Gone in 60 Seconds 237202299 101648571 42.9 135553728 57.1 2000 Action, Crime, Thriller 6.433/10 4438 en United States of America
16 Chicken Run 224834564 106834564 47.5 118000000 52.5 2000 Animation, Comedy, Family 6.822/10 5040 en France, United Kingdom, United States of America
17 Vertical Limit 215663859 69243859 32.1 146420000 67.9 2000 Adventure, Action, Thriller 6.011/10 1025 en Germany, United States of America
18 The Patriot 215294342 113330342 52.6 101964000 47.4 2000 Drama, History, War, Action 7.183/10 3926 en Germany, United States of America
19 Crouching Tiger, Hidden Dragon 213525736 128078872 60.0 85446864 40.0 2000 Adventure, Drama, Action, Romance 7.43/10 3213 zh Hong Kong, Taiwan, United States of America
20 Miss Congeniality 212742720 106807667 50.2 105935053 49.8 2000 Comedy, Crime, Action 6.531/10 3900 en United States of America

Dimensiones

dim(datos)
## [1] 5000   13

El resultado muestra un data frame con 5.000 observaciones(filas) y 13 variables(columnas). Este tamaño de muestra es suficiente para realizar un análisis significativo, ya que permite identificar patrones y relaciones en los datos.

Nombres de las Variables y Tipo de Dato (Estructura):

names(datos)
##  [1] "Rank"                 "Release.Group"        "X.Worldwide"         
##  [4] "X.Domestic"           "Domestic.."           "X.Foreign"           
##  [7] "Foreign.."            "Year"                 "Genres"              
## [10] "Rating"               "Vote_Count"           "Original_Language"   
## [13] "Production_Countries"
sapply(datos, class)
##                 Rank        Release.Group          X.Worldwide 
##            "integer"          "character"            "numeric" 
##           X.Domestic           Domestic..            X.Foreign 
##            "numeric"            "numeric"            "numeric" 
##            Foreign..                 Year               Genres 
##            "numeric"            "integer"          "character" 
##               Rating           Vote_Count    Original_Language 
##          "character"            "numeric"          "character" 
## Production_Countries 
##          "character"

Clasificación de las Variables:

Cualitativas/categóricas:

  • Release Group: El título de la película o serie de películas.

  • Genres: Los géneros asociados a la película (por ejemplo, acción, drama, comedia).

  • Original Language: El idioma principal de la película.

  • Production Countries: Los países donde se produjo la película.

Cuantitativas/númericas:

  • Rank: La clasificación global de la película basada en los ingresos de taquilla en todo el mundo.

  • Worldwide: Ingresos totales de taquilla de la película en todo el mundo

  • Domestic: Ingresos totales de taquilla nacional (local)

  • Domestic %: Porcentaje de los ingresos mundiales generados en el país.

  • Foreign: Ingresos totales de la taquilla extranjera (internacional)

  • Foreign %: Porcentaje de ingresos mundiales generados en mercados extranjeros.

  • Year: Año de estreno de la película.

  • Rating: Calificación media del público según TMDB (por ejemplo, 7,5/10).

  • Vote Count: The number of votes the movie received on TMDB.

str(datos)
## 'data.frame':    5000 obs. of  13 variables:
##  $ Rank                : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Release.Group       : chr  "Mission: Impossible II" "Gladiator" "Cast Away" "What Women Want" ...
##  $ X.Worldwide         : num  5.46e+08 4.61e+08 4.30e+08 3.74e+08 3.50e+08 ...
##  $ X.Domestic          : num  2.15e+08 1.88e+08 2.34e+08 1.83e+08 1.38e+08 ...
##  $ Domestic..          : num  39.4 40.8 54.4 48.9 39.4 75.4 50.3 55.6 53.1 53.3 ...
##  $ X.Foreign           : num  3.31e+08 2.73e+08 1.96e+08 1.91e+08 2.12e+08 ...
##  $ Foreign..           : num  60.6 59.2 45.6 51.1 60.6 24.6 49.7 44.4 46.9 46.7 ...
##  $ Year                : int  2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 ...
##  $ Genres              : chr  "Adventure, Action, Thriller" "Action, Drama, Adventure" "Adventure, Drama" "Comedy, Romance" ...
##  $ Rating              : chr  "6.126/10" "8.217/10" "7.663/10" "6.45/10" ...
##  $ Vote_Count          : num  6741 19032 11403 3944 2530 ...
##  $ Original_Language   : chr  "en" "en" "en" "en" ...
##  $ Production_Countries: chr  "United States of America" "United Kingdom, United States of America" "United States of America" "United Kingdom, United States of America" ...

A continuación se presenta la tabla de operacionalización de variables utilizando el paquete knitr, que organiza la clasificación de las variables según su tipo y subtipo:

operacionalizacion <- data.frame(
  Variable = c("Rank", "Worldwide", "Domestic", "Domestic %", "Foreign", "Foreign %", 
               "Year", "Rating", "Vote Count", "Release Group", "Genres", 
               "Original Language", "Production Countries"),
  
  Definición = c(
    "Posición de la película en el ranking de recaudación global.",
    "Ingresos totales de la película a nivel mundial.",
    "Ingresos obtenidos en el mercado doméstico (país de origen).",
    "Porcentaje de los ingresos mundiales obtenidos en el mercado doméstico.",
    "Ingresos obtenidos en mercados internacionales.",
    "Porcentaje de los ingresos mundiales obtenidos en mercados internacionales.",
    "Año de estreno de la película.",
    "Calificación promedio en TMDB basada en la opinión de los usuarios.",
    "Cantidad total de votos recibidos en TMDB.",
    "Nombre de la película o de la franquicia a la que pertenece.",
    "Géneros asociados a la película.",
    "Idioma principal en el que fue filmada la película.",
    "País o países donde se produjo la película."
  ),
  
  Naturaleza = c("Cuantitativa discreta", "Cuantitativa continua", "Cuantitativa continua", 
                 "Cuantitativa continua", "Cuantitativa continua", "Cuantitativa continua", 
                 "Cuantitativa discreta", "Cuantitativa continua", "Cuantitativa discreta", 
                 "Cualitativa", "Cualitativa", "Cualitativa", 
                 "Cualitativa"),
  
  Nivel_de_Medicion = c("De razón", "De razón", "De razón", 
                        "De razón", "De razón", "De razón", 
                        "De razón", "De razón", "De razón", 
                        "Nominal", "Nominal", "Nominal", "Nominal"),
  
  Criterio_Clasificacion = c("Numeración entre [1-200].",
    "Valor numérico en dólares.",
    "Valor numérico en dólares.",
    "Porcentaje entre 0% y 100%.",
    "Valor numérico en dólares.",
    "Porcentaje entre 0% y 100%.",
    "Número entero entre 2000 y 2024.",
    "Número decimal en escala de 0 a 10.",
    "Número entero que indica la cantidad de votos.",
    "Cadena de caracteres con el nombre oficial de la película o franquicia.",
    "Categorías establecidas: Acción, Drama, Comedia, etc.",
    "Códigos ISO 639-1 de idioma (ej. 'en', 'es').",
    "Códigos de país en formato ISO 3166-1 alpha-2 (ej. 'US', 'FR')."
  ),
   
  stringsAsFactors = FALSE # Para evitar que se conviertan en factores
)

operacionalizacion %>%
  kbl(caption = "Tabla de Operacionalización de Variables") %>%
  kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed", "responsive"), 
                font_size = 14, position = "center") %>%
  row_spec(0, bold = TRUE, color = "white", background = "#0073C2FF") %>% 
  row_spec(1:nrow(operacionalizacion), background = "lightgray")  
Tabla de Operacionalización de Variables
Variable Definición Naturaleza Nivel_de_Medicion Criterio_Clasificacion
Rank Posición de la película en el ranking de recaudación global. Cuantitativa discreta De razón Numeración entre [1-200].
Worldwide Ingresos totales de la película a nivel mundial. Cuantitativa continua De razón Valor numérico en dólares.
Domestic Ingresos obtenidos en el mercado doméstico (país de origen). Cuantitativa continua De razón Valor numérico en dólares.
Domestic % Porcentaje de los ingresos mundiales obtenidos en el mercado doméstico. Cuantitativa continua De razón Porcentaje entre 0% y 100%.
Foreign Ingresos obtenidos en mercados internacionales. Cuantitativa continua De razón Valor numérico en dólares.
Foreign % Porcentaje de los ingresos mundiales obtenidos en mercados internacionales. Cuantitativa continua De razón Porcentaje entre 0% y 100%.
Year Año de estreno de la película. Cuantitativa discreta De razón Número entero entre 2000 y 2024.
Rating Calificación promedio en TMDB basada en la opinión de los usuarios. Cuantitativa continua De razón Número decimal en escala de 0 a 10.
Vote Count Cantidad total de votos recibidos en TMDB. Cuantitativa discreta De razón Número entero que indica la cantidad de votos.
Release Group Nombre de la película o de la franquicia a la que pertenece. Cualitativa Nominal Cadena de caracteres con el nombre oficial de la película o franquicia.
Genres Géneros asociados a la película. Cualitativa Nominal Categorías establecidas: Acción, Drama, Comedia, etc.
Original Language Idioma principal en el que fue filmada la película. Cualitativa Nominal Códigos ISO 639-1 de idioma (ej. ‘en’, ‘es’).
Production Countries País o países donde se produjo la película. Cualitativa Nominal Códigos de país en formato ISO 3166-1 alpha-2 (ej. ‘US’, ‘FR’).

Limpieza del Dataset

Antes de proceder con el análisis exploratorio, se llevó a cabo una limpieza de datos para garantizar la calidad y confiabilidad de los resultados. Este proceso incluyó la identificación y tratamiento de valores faltantes, asegurando así un conjunto de datos adecuado para el análisis.

Nota: Si bien los outliers suelen tratarse o eliminarse en algunos análisis, en este caso es importante considerar su relevancia.

Identificación y Tratamiento de Valores Faltantes

Se evaluó la presencia de valores faltantes en cada una de las variables:

colSums(is.na(datos))
##                 Rank        Release.Group          X.Worldwide 
##                    0                    0                    0 
##           X.Domestic           Domestic..            X.Foreign 
##                    0                    0                    0 
##            Foreign..                 Year               Genres 
##                    0                    0                    0 
##               Rating           Vote_Count    Original_Language 
##                    0                  170                    0 
## Production_Countries 
##                    0

Hemos identificado que los valores nulos en nuestro dataset están presentes únicamente en la variable Vote_Count Dado que los datos faltantes pueden afectar el análisis y la interpretación de los resultados, es importante determinar la mejor estrategia para su tratamiento.

Para ello, analizaremos la distribución de los valores en esta columna y compararemos la media y la mediana. Si la distribución es simétrica y no presenta valores extremos, utilizaremos la media para imputar los valores faltantes. Sin embargo, si la variable muestra sesgo o contiene outliers significativos, la mediana será una mejor opción.

summary(datos$Vote_Count)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0   205.2  1035.5  2531.6  3065.0 36753.0     170
hist(datos$Vote_Count, main="Distribución de Vote_Count", col="orange", breaks=30)

El análisis de esta variable muestra que su distribución está altamente sesgada a la derecha, con valores extremos que indican la presencia de valores atípicos.

Estrategia para el tratamiento

Dado que la media es sensible a los valores atípicos, utilizarla para imputar los valores faltantes podría distorsionar los datos. En cambio, la mediana es una mejor opción, ya que es menos afectada por los valores atípicos y representa con mayor precisión la tendencia central de la variable.

datos$Vote_Count[is.na(datos$Vote_Count)] <- median(datos$Vote_Count, na.rm = TRUE)

Con esta imputación, aseguramos que los datos faltantes sean tratados de manera robusta, evitando que los valores extremos introduzcan sesgos en los análisis posteriores.

A continuación, procederemos a verificar la correcta imputación de los valores nulos.

sum(is.na(datos$Vote_Count))
## [1] 0
data_omit <- na.omit(datos)

ggp1 <- ggplot(data.frame(value=datos$Vote_Count), aes(x=value)) +
  geom_histogram(fill="#FD0000", color="#E52521", alpha=0.9) +
  ggtitle("Original data") +
  xlab("Vote_Count") + ylab("Frequency") +
  theme_ipsum() +
  theme(plot.title = element_text(size=15))

ggp2 <- ggplot(data.frame(value=data_omit$Vote_Count), aes(x=value)) +
  geom_histogram(fill="#43B047", color="#049DCB", alpha=0.9) +
  ggtitle("Reemplazado por Mediana") +
  xlab("Vote_Count") + ylab("Frequency") +
  theme_ipsum() +
  theme(plot.title = element_text(size=15))

grid.arrange(ggp1, ggp2, ncol = 2)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font family
## not found in Windows font database
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : font
## family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database
## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## font family not found in Windows font database

Resumen estadístico

En esta sección se presenta el Resumen Estadístico del dataset. El análisis de las variables cualitativas se realiza mediante tablas de frecuencia y diagramas de barras, que muestran la distribución de las categorías en cada una. Esto es esencial para identificar cómo se distribuyen las observaciones entre las distintas categorías.

Por otro lado, el análisis de las variables cuantitativas incluye un resumen estadístico que muestra medidas como la media, mediana, mínimo, máximo y los cuartiles. Estas medidas son clave para comprender la dispersión y tendencia central de los datos numéricos.

# Resumen estadístico detallado
describe(datos)
##                       vars    n         mean           sd      median
## Rank                     1 5000       100.50        57.74      100.50
## Release.Group*           2 5000      2476.38      1429.50     2472.50
## X.Worldwide              3 5000 119213693.21 200524343.22 48446575.00
## X.Domestic               4 5000  44725232.97  77270255.71 17984212.00
## Domestic..               5 5000        35.74        30.66       37.05
## X.Foreign                6 5000  74488092.74 133493209.86 30194438.00
## Foreign..                7 5000        64.26        30.65       62.95
## Year                     8 5000      2012.00         7.21     2012.00
## Genres*                  9 5000       625.95       357.22      641.00
## Rating*                 10 5000       874.39       509.46      880.50
## Vote_Count              11 5000      2480.72      3888.06     1035.50
## Original_Language*      12 5000        11.33         7.74        8.00
## Production_Countries*   13 5000       360.46       146.77      428.00
##                           trimmed         mad     min        max      range
## Rank                       100.50       74.13       1        200        199
## Release.Group*            2475.78     1836.20       1       4955       4954
## X.Worldwide           73234312.39 45680791.13 1666028 2799439100 2797773072
## X.Domestic            27606016.52 26663392.71       0  936662225  936662225
## Domestic..                  33.29       43.59       0        100        100
## X.Foreign             43728724.38 31159440.96       0 1993811448 1993811448
## Foreign..                   66.71       43.59       0        100        100
## Year                      2012.00        8.90    2000       2024         24
## Genres*                    627.65      357.31       1       1318       1317
## Rating*                    875.98      610.09       1       1830       1829
## Vote_Count                1599.73     1400.32       0      36753      36753
## Original_Language*           9.69        0.00       1         36         35
## Production_Countries*      385.23       68.20       1        511        510
##                        skew kurtosis         se
## Rank                   0.00    -1.20       0.82
## Release.Group*         0.00    -1.20      20.22
## X.Worldwide            4.49    30.70 2835842.46
## X.Domestic             3.98    23.63 1092766.44
## Domestic..             0.31    -1.03       0.43
## X.Foreign              4.69    34.22 1887879.08
## Foreign..             -0.31    -1.03       0.43
## Year                   0.00    -1.20       0.10
## Genres*               -0.08    -0.90       5.05
## Rating*               -0.03    -1.07       7.20
## Vote_Count             3.14    12.97      54.99
## Original_Language*     2.06     3.78       0.11
## Production_Countries* -1.12    -0.03       2.08

Variables CUALITATIVAS/CATEGÓRICAS

Para analizar las variables cualitativas del conjunto de datos, se generaron tablas de frecuencia para Género, Idioma Original y País de Producción. Estas tablas muestran las 10 categorías más frecuentes en cada caso, seguidas de una fila agregada con la categoría “Otros” para agrupar el resto de los valores menos frecuentes. Finalmente, se incluyó una fila correspondiente a la moda, que representa la categoría con mayor aparición dentro de cada variable.

NOTA: No se generó una tabla de frecuencia para la variable Release Group, ya que esta contiene nombres únicos de películas. Dado que cada película tiene un título distinto, su frecuencia es generalmente 1 en la mayoría de los casos, lo que haría que la tabla de frecuencias no sea útil para el análisis.

resumen_categorico <- function(variable, nombre_variable, moda, top_n = 10) {
  
  variable <- unlist(strsplit(as.character(variable), ", "))
  
  frecuencias <- as.data.frame(table(variable)) %>%
    arrange(desc(Freq)) %>%
    rename(Categoria = variable, Frecuencia_Absoluta = Freq)
  
  total_frecuencia <- sum(frecuencias$Frecuencia_Absoluta)
  frecuencias <- frecuencias %>%
    mutate(Frecuencia_Relativa = round((Frecuencia_Absoluta / total_frecuencia) * 100, 2),
           Frecuencia_Acumulada = cumsum(Frecuencia_Absoluta))
  
  if (nrow(frecuencias) > top_n) {
    otros <- sum(frecuencias$Frecuencia_Absoluta[(top_n+1):nrow(frecuencias)])
    frecuencias <- frecuencias[1:top_n, ]
    
    frecuencias <- rbind(frecuencias, 
                         data.frame(Categoria = "Otros", 
                                    Frecuencia_Absoluta = otros, 
                                    Frecuencia_Relativa = round((otros / total_frecuencia) * 100, 2),
                                    Frecuencia_Acumulada = sum(frecuencias$Frecuencia_Absoluta) + otros))
    
    frecuencias <- rbind(frecuencias, 
                         data.frame(Categoria = "Total", 
                                    Frecuencia_Absoluta = total_frecuencia, 
                                    Frecuencia_Relativa = 100,
                                    Frecuencia_Acumulada = ""))
    
    frecuencias <- rbind(frecuencias, 
                         data.frame(Categoria = moda, 
                                    Frecuencia_Absoluta = "",
                                    Frecuencia_Relativa = "",
                                    Frecuencia_Acumulada = ""))
  }
  
  tabla_kable <- frecuencias %>%
    kbl(caption = paste("Resumen de frecuencias para", nombre_variable), digits = 2, align = "c") %>%
    kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed"), 
                  font_size = 12, position = "center") %>%
    column_spec(1, bold = TRUE, background = "lightblue") %>%
    row_spec(nrow(frecuencias) - 2, bold = TRUE, color = "white", background = "darkgrey") %>%  
    row_spec(nrow(frecuencias) - 1, bold = TRUE, color = "black", background = "lightgrey") %>%  
    row_spec(nrow(frecuencias), bold = TRUE, color = "white", background = "darkblue")    
  
  return(tabla_kable)
}
resumen_categorico(datos$Genres, "Género", "Moda: Drama")
Resumen de frecuencias para Género
Categoria Frecuencia_Absoluta Frecuencia_Relativa Frecuencia_Acumulada
Drama 2009 15.6 2009
Comedy 1907 14.8 3916
Action 1384 10.74 5300
Adventure 1063 8.25 6363
Thriller 1060 8.23 7423
Romance 844 6.55 8267
Crime 699 5.43 8966
Family 694 5.39 9660
Fantasy 634 4.92 10294
Science Fiction 514 3.99 10808
Otros 2074 16.1 12882
Total 12882 100
Moda: Drama
resumen_categorico(datos$Original_Language, "Idioma Original", "Moda: English (en)")
Resumen de frecuencias para Idioma Original
Categoria Frecuencia_Absoluta Frecuencia_Relativa Frecuencia_Acumulada
en 3271 67.72 3271
ja 369 7.64 3640
zh 280 5.8 3920
fr 203 4.2 4123
ko 194 4.02 4317
hi 92 1.9 4409
de 77 1.59 4486
es 63 1.3 4549
cn 61 1.26 4610
it 56 1.16 4666
Otros 164 3.4 4830
Total 4830 100
Moda: English (en)
resumen_categorico(datos$Production_Countries, "País de Producción", "Moda: United States of America")
Resumen de frecuencias para País de Producción
Categoria Frecuencia_Absoluta Frecuencia_Relativa Frecuencia_Acumulada
United States of America 3153 43.72 3153
United Kingdom 616 8.54 3769
France 454 6.3 4223
Japan 436 6.05 4659
China 394 5.46 5053
Germany 362 5.02 5415
Canada 243 3.37 5658
South Korea 214 2.97 5872
Hong Kong 191 2.65 6063
India 158 2.19 6221
Otros 991 13.74 7212
Total 7212 100
Moda: United States of America

Análisis:
- El género más frecuente en la base de datos es Drama, con 2,009 películas, representando el 15.6% del total. Le siguen Comedy (14.8%) y Action (10.74%). Los géneros menos frecuentes incluyen Science Fiction (3.99%). La categoría “Otros” agrupa géneros con menor presencia (2,074 películas).
- El idioma predominante es inglés (en), con el 67.72% de las películas, lo que indica un fuerte dominio de esta lengua en la industria cinematográfica. Otros idiomas como japonés (ja) (7.64%) y chino (zh) (5.8%) también tienen cierta representación. Los demás idiomas tienen frecuencias relativamente bajas.
- Los Estados Unidos dominan la producción con 43.72% de las películas, seguidos por Reino Unido (8.54%) y Francia (6.3%). Los países con menor representación en el top 10 incluyen India (2.19%). La categoría “Otros” agrupa el 13.74% de las películas, indicando una dispersión de producciones en diversos países.

Representación gráfica:

datos_separados <- datos %>%
  separate_rows(Genres, sep = ",\\s*")  # Divide los géneros correctamente

freq_genres <- datos_separados %>%
  count(Genres, sort = TRUE) %>%
  top_n(12, n)

ggplot(freq_genres, aes(x = reorder(Genres, n), y = n, fill = n)) +
  geom_bar(stat = "identity", show.legend = FALSE) +
  scale_fill_viridis_c(option = "plasma") +  
  coord_flip() +  
  geom_text(aes(label = n), hjust = -0.2, size = 5, color = "black") +  
  expand_limits(y = max(freq_genres$n) * 1.2) + 
  labs(title = "🎬 Distribución de Géneros de Películas", 
       x = "Géneros", 
       y = "Frecuencia") +
  theme_minimal(base_size = 12) + 
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 18),
        axis.text.x = element_text(size = 12),
        axis.text.y = element_text(size = 12, face = "bold"),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.background = element_rect(fill = "#F8F8F8", color = NA))

datos_filtrados <- datos %>%
  filter(Original_Language != "", !is.na(Original_Language))  # Elimina valores vacíos o NA


freq_language <- datos_filtrados %>%
  count(Original_Language, name = "Freq") %>%
  mutate(Percentage = round((Freq / sum(Freq)) * 100, 1)) %>%
  arrange(Freq) %>%
  slice_tail(n = 15)  
# Graficar
ggplot(freq_language, aes(x = reorder(Original_Language, Freq), y = Freq, fill = Freq)) +
  geom_bar(stat = "identity", color = "black") +
  geom_text(aes(label = paste(Freq, "(", Percentage, "%)", sep = "")), hjust = -0.18, size = 4) +
  scale_fill_viridis_c(option = "magma", direction = -1) +
  labs(title = "Distribución de Idiomas Originales en Películas",
       x = "Idiomas",
       y = "Frecuencia") +
  theme_minimal(base_size = 16) +
  theme(panel.grid.major = element_line(color = "grey90"),
        panel.border = element_rect(color = "grey50", fill = NA),
        plot.title = element_text(hjust = 0.5, face = "bold"),
        axis.text.x = element_text(angle = 45, hjust = 1)) +
  expand_limits(y = max(freq_language$Freq) * 1.2) +
  coord_flip()

A continuación se visualiza un diccionarios con el idioma correspondiente a las abreviaciones en la base de datos:

df_idiomas <- data.frame(
  Código = c("en", "ja", "zh", "fr", "ko", "hi", "de", "es", "cn", "it", "ru", "tr", "te", "sv"),
  Idioma = c("Inglés", "Japonés", "Chino", "Francés", "Coreano", "Hindi", 
             "Alemán", "Español", "Chino (simplificado)", "Italiano", 
             "Ruso", "Turco", "Telugu", "Sueco")
)
df_idiomas %>%
  gt() %>%
  tab_header(
    title = "Diccionario de Abreviaciones de Idiomas"
  ) %>%
  cols_align(align = "center", columns = everything()) %>%
  tab_style(
    style = list(
      cell_borders(sides = "all", weight = px(1)),
      cell_fill(color = "#f5f5f5")
    ),
    locations = cells_body()
  )
Diccionario de Abreviaciones de Idiomas
Código Idioma
en Inglés
ja Japonés
zh Chino
fr Francés
ko Coreano
hi Hindi
de Alemán
es Español
cn Chino (simplificado)
it Italiano
ru Ruso
tr Turco
te Telugu
sv Sueco
df_paises <- as.data.frame(table(unlist(strsplit(as.character(datos$Production_Countries), ", "))))

colnames(df_paises) <- c("Production_Countries", "Frecuencia")

df_paises <- df_paises %>% arrange(desc(Frecuencia))

top_paises <- head(df_paises, 10)

ggplot(top_paises, aes(x = Frecuencia, y = reorder(Production_Countries, Frecuencia), fill = Frecuencia)) +
  geom_col() +
  geom_text(aes(label = Frecuencia), hjust = -0.2, fontface = "bold", size = 4) + 
  expand_limits(x = max(top_paises$Frecuencia) * 1.2) +  
  scale_fill_gradient(low = "yellow", high = "blue") +  
  labs(title = "Distribución de Países de Producción",
       x = "Frecuencia",
       y = "Países") +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 16))

Variables CUANTITATIVAS/NUMÉRICAS:

Para analizar las variables cuantitativas del conjunto de datos, se calcularon estadísticas descriptivas como la media, mediana, desviación estándar, mínimo y máximo. Estas métricas permiten comprender la distribución y variabilidad de cada variable. Además, se realiza el analisis de medidas de tendencia central y de dispersión.

datos_numericos <- datos[, sapply(datos, is.numeric)]

summary(datos_numericos)
##       Rank         X.Worldwide          X.Domestic          Domestic..    
##  Min.   :  1.00   Min.   :1.666e+06   Min.   :        0   Min.   :  0.00  
##  1st Qu.: 50.75   1st Qu.:2.466e+07   1st Qu.:    92752   1st Qu.:  0.20  
##  Median :100.50   Median :4.845e+07   Median : 17984212   Median : 37.05  
##  Mean   :100.50   Mean   :1.192e+08   Mean   : 44725233   Mean   : 35.74  
##  3rd Qu.:150.25   3rd Qu.:1.198e+08   3rd Qu.: 53868472   3rd Qu.: 57.80  
##  Max.   :200.00   Max.   :2.799e+09   Max.   :936662225   Max.   :100.00  
##    X.Foreign           Foreign..           Year        Vote_Count     
##  Min.   :0.000e+00   Min.   :  0.00   Min.   :2000   Min.   :    0.0  
##  1st Qu.:1.371e+07   1st Qu.: 42.20   1st Qu.:2006   1st Qu.:  226.5  
##  Median :3.019e+07   Median : 62.95   Median :2012   Median : 1035.5  
##  Mean   :7.449e+07   Mean   : 64.26   Mean   :2012   Mean   : 2480.7  
##  3rd Qu.:7.212e+07   3rd Qu.: 99.80   3rd Qu.:2018   3rd Qu.: 2939.0  
##  Max.   :1.994e+09   Max.   :100.00   Max.   :2024   Max.   :36753.0

Análisis de Correlación

# Calcular la matriz de correlación
correlation_matrix <- cor(datos[, c("X.Worldwide", "X.Domestic", "X.Foreign", "Vote_Count")], use = "complete.obs")

# Visualizar la matriz de correlación
library(reshape2)
library(ggplot2)

correlation_melted <- melt(correlation_matrix)
ggplot(correlation_melted, aes(Var1, Var2, fill = value)) + 
  geom_tile() + 
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", limit = c(-1, 1), name="Correlación") +
  theme_minimal() +
  labs(title = "Mapa de Calor de Correlación")

Relaciones clave:

  • X.Worldwide vs. X.Domestic y X.Foreign: Se observa un rojo intenso, lo que sugiere que los ingresos mundiales tienen una fuerte correlación tanto con los ingresos domésticos como con los extranjeros (lógico, ya que son sus componentes).
  • Vote_Count vs. X.Worldwide/X.Domestic/X.Foreign: También hay una correlación positiva, lo que indica que películas con más ingresos suelen recibir más votos (puede deberse a mayor popularidad).
  • X.Domestic vs. X.Foreign: No parece ser una correlación perfecta, lo que sugiere que una película puede tener éxito en un mercado y no necesariamente en el otro.

Tablas de frecuencias agrupadas

datos_filtrados <- datos$X.Worldwide[is.finite(datos$X.Worldwide) & !is.na(datos$X.Worldwide)] # Eliminar valores no finitos

# Definir los intervalos
intervalos <- cut(datos_filtrados, breaks = seq(min(datos_filtrados, na.rm = TRUE), max(datos_filtrados, na.rm = TRUE), length.out = 10), include.lowest = TRUE)

# Calcular las frecuencias absoluta, relativa y acumulada
frecuencia_absoluta <- table(intervalos)
frecuencia_relativa <- prop.table(frecuencia_absoluta)
frecuencia_acumulada <- cumsum(frecuencia_absoluta)
frecuencia_relativa_porcentaje <- frecuencia_relativa * 100
# Crear la tabla de frecuencias
tabla_frecuencias <- data.frame(
  Intervalo = names(frecuencia_absoluta),
  Frecuencia_Absoluta = as.numeric(frecuencia_absoluta),
  Frecuencia_Acumulada = as.numeric(frecuencia_acumulada),
  Frecuencia_Relativa = round(as.numeric(frecuencia_relativa_porcentaje), 2) # En porcentaje
)
# Fila al final con los totales
totales <- data.frame(
  Intervalo = "Total",
  Frecuencia_Absoluta = sum(tabla_frecuencias$Frecuencia_Absoluta),
  Frecuencia_Acumulada = NA, # No tiene sentido acumular en la fila total
  Frecuencia_Relativa = sum(tabla_frecuencias$Frecuencia_Relativa)
)
tabla_frecuencias <- rbind(tabla_frecuencias, totales)
# Mostrar la tabla usando kable
library(kableExtra)
tabla_frecuencias %>%
  kbl(caption = "Tabla de Frecuencias Agrupadas para la variable X.Worldwide", align = "c") %>%
  kable_styling(full_width = F, position = "center", font_size = 12) %>%
  row_spec(nrow(tabla_frecuencias), bold = TRUE, color = "white", background = "gray") 
Tabla de Frecuencias Agrupadas para la variable X.Worldwide
Intervalo Frecuencia_Absoluta Frecuencia_Acumulada Frecuencia_Relativa
[1.67e+06,3.13e+08] 4542 4542 90.84
(3.13e+08,6.23e+08] 287 4829 5.74
(6.23e+08,9.34e+08] 107 4936 2.14
(9.34e+08,1.25e+09] 41 4977 0.82
(1.25e+09,1.56e+09] 14 4991 0.28
(1.56e+09,1.87e+09] 3 4994 0.06
(1.87e+09,2.18e+09] 3 4997 0.06
(2.18e+09,2.49e+09] 1 4998 0.02
(2.49e+09,2.8e+09] 2 5000 0.04
Total 5000 NA 100.00

La distribución de las recaudaciones globales de las películas muestra una alta concentración en valores bajos, con la mayoría de las películas generando ingresos moderados, mientras que un pequeño porcentaje alcanza cifras significativamente más altas. Esto refleja una distribución desigual en la industria, donde unas pocas películas muy exitosas dominan el mercado, mientras que la mayoría se quedan con ingresos más modestos. La mayor parte del total de recaudaciones está agrupada en un pequeño número de películas de gran éxito, mientras que el resto tiene un rendimiento más equilibrado o bajo.

datos_filtrados <- datos$Domestic[is.finite(datos$Domestic) & !is.na(datos$Domestic)] # Eliminar valores no finitos

# Definir los intervalos
intervalos <- cut(datos_filtrados, breaks = seq(min(datos_filtrados, na.rm = TRUE), max(datos_filtrados, na.rm = TRUE), length.out = 10), include.lowest = TRUE)

# Calcular las frecuencias absoluta, relativa y acumulada
frecuencia_absoluta <- table(intervalos)
frecuencia_relativa <- prop.table(frecuencia_absoluta)
frecuencia_acumulada <- cumsum(frecuencia_absoluta)
frecuencia_relativa_porcentaje <- frecuencia_relativa * 100
# Crear la tabla de frecuencias
tabla_frecuencias <- data.frame(
  Intervalo = names(frecuencia_absoluta),
  Frecuencia_Absoluta = as.numeric(frecuencia_absoluta),
  Frecuencia_Acumulada = as.numeric(frecuencia_acumulada),
  Frecuencia_Relativa = round(as.numeric(frecuencia_relativa_porcentaje), 2) # En porcentaje
)
# Fila al final con los totales
totales <- data.frame(
  Intervalo = "Total",
  Frecuencia_Absoluta = sum(tabla_frecuencias$Frecuencia_Absoluta),
  Frecuencia_Acumulada = NA, # No tiene sentido acumular en la fila total
  Frecuencia_Relativa = sum(tabla_frecuencias$Frecuencia_Relativa)
)
tabla_frecuencias <- rbind(tabla_frecuencias, totales)
# Mostrar la tabla usando kable
library(kableExtra)
tabla_frecuencias %>%
  kbl(caption = "Tabla de Frecuencias Agrupadas para la variable Domestic", align = "c") %>%
  kable_styling(full_width = F, position = "center", font_size = 12) %>%
  row_spec(nrow(tabla_frecuencias), bold = TRUE, color = "white", background = "gray") 
Tabla de Frecuencias Agrupadas para la variable Domestic
Intervalo Frecuencia_Absoluta Frecuencia_Acumulada Frecuencia_Relativa
[0,11.1] 1689 1689 33.78
(11.1,22.2] 208 1897 4.16
(22.2,33.3] 415 2312 8.30
(33.3,44.4] 610 2922 12.20
(44.4,55.6] 711 3633 14.22
(55.6,66.7] 494 4127 9.88
(66.7,77.8] 348 4475 6.96
(77.8,88.9] 231 4706 4.62
(88.9,100] 294 5000 5.88
Total 5000 NA 100.00

La distribución de las recaudaciones domésticas de las películas está concentrada en valores bajos, con un 33.78% de las películas obteniendo ingresos dentro del primer intervalo (0 a 11.1). Aunque hay una distribución más variada, la mayoría de las películas tienen ingresos relativamente bajos, con una disminución gradual en la frecuencia a medida que aumentan las recaudaciones.

datos_filtrados <- datos$Foreign[is.finite(datos$Foreign) & !is.na(datos$Foreign)] # Eliminar valores no finitos

# Definir los intervalos
intervalos <- cut(datos_filtrados, breaks = seq(min(datos_filtrados, na.rm = TRUE), max(datos_filtrados, na.rm = TRUE), length.out = 10), include.lowest = TRUE)

# Calcular las frecuencias absoluta, relativa y acumulada
frecuencia_absoluta <- table(intervalos)
frecuencia_relativa <- prop.table(frecuencia_absoluta)
frecuencia_acumulada <- cumsum(frecuencia_absoluta)
frecuencia_relativa_porcentaje <- frecuencia_relativa * 100
# Crear la tabla de frecuencias
tabla_frecuencias <- data.frame(
  Intervalo = names(frecuencia_absoluta),
  Frecuencia_Absoluta = as.numeric(frecuencia_absoluta),
  Frecuencia_Acumulada = as.numeric(frecuencia_acumulada),
  Frecuencia_Relativa = round(as.numeric(frecuencia_relativa_porcentaje), 2) # En porcentaje
)
# Fila al final con los totales
totales <- data.frame(
  Intervalo = "Total",
  Frecuencia_Absoluta = sum(tabla_frecuencias$Frecuencia_Absoluta),
  Frecuencia_Acumulada = NA, # No tiene sentido acumular en la fila total
  Frecuencia_Relativa = sum(tabla_frecuencias$Frecuencia_Relativa)
)
tabla_frecuencias <- rbind(tabla_frecuencias, totales)
# Mostrar la tabla usando kable
library(kableExtra)
tabla_frecuencias %>%
  kbl(caption = "Tabla de Frecuencias Agrupadas para la variable Foreign", align = "c") %>%
  kable_styling(full_width = F, position = "center", font_size = 12) %>%
  row_spec(nrow(tabla_frecuencias), bold = TRUE, color = "white", background = "gray") 
Tabla de Frecuencias Agrupadas para la variable Foreign
Intervalo Frecuencia_Absoluta Frecuencia_Acumulada Frecuencia_Relativa
[0,11.1] 294 294 5.88
(11.1,22.2] 231 525 4.62
(22.2,33.3] 348 873 6.96
(33.3,44.4] 494 1367 9.88
(44.4,55.6] 711 2078 14.22
(55.6,66.7] 610 2688 12.20
(66.7,77.8] 415 3103 8.30
(77.8,88.9] 208 3311 4.16
(88.9,100] 1689 5000 33.78
Total 5000 NA 100.00

La distribución de las recaudaciones internacionales de las películas está más equilibrada en comparación con el mercado doméstico. Si bien la mayor parte de las películas aún se concentran en intervalos de recaudación más bajos, existe una mayor proporción de películas con altos ingresos en el mercado internacional.

datos_filtrados <- datos$Vote_Count[is.finite(datos$Vote_Count) & !is.na(datos$Vote_Count)] # Eliminar valores no finitos

# Definir los intervalos
intervalos <- cut(datos_filtrados, breaks = seq(min(datos_filtrados, na.rm = TRUE), max(datos_filtrados, na.rm = TRUE), length.out = 10), include.lowest = TRUE)

# Calcular las frecuencias absoluta, relativa y acumulada
frecuencia_absoluta <- table(intervalos)
frecuencia_relativa <- prop.table(frecuencia_absoluta)
frecuencia_acumulada <- cumsum(frecuencia_absoluta)
frecuencia_relativa_porcentaje <- frecuencia_relativa * 100
# Crear la tabla de frecuencias
tabla_frecuencias <- data.frame(
  Intervalo = names(frecuencia_absoluta),
  Frecuencia_Absoluta = as.numeric(frecuencia_absoluta),
  Frecuencia_Acumulada = as.numeric(frecuencia_acumulada),
  Frecuencia_Relativa = round(as.numeric(frecuencia_relativa_porcentaje), 2) # En porcentaje
)
# Fila al final con los totales
totales <- data.frame(
  Intervalo = "Total",
  Frecuencia_Absoluta = sum(tabla_frecuencias$Frecuencia_Absoluta),
  Frecuencia_Acumulada = NA, # No tiene sentido acumular en la fila total
  Frecuencia_Relativa = sum(tabla_frecuencias$Frecuencia_Relativa)
)
tabla_frecuencias <- rbind(tabla_frecuencias, totales)
# Mostrar la tabla usando kable
library(kableExtra)
tabla_frecuencias %>%
  kbl(caption = "Tabla de Frecuencias Agrupadas para la variable Vote_Count", align = "c") %>%
  kable_styling(full_width = F, position = "center", font_size = 12) %>%
  row_spec(nrow(tabla_frecuencias), bold = TRUE, color = "white", background = "gray") 
Tabla de Frecuencias Agrupadas para la variable Vote_Count
Intervalo Frecuencia_Absoluta Frecuencia_Acumulada Frecuencia_Relativa
[0,4.08e+03] 4099 4099 81.98
(4.08e+03,8.17e+03] 534 4633 10.68
(8.17e+03,1.23e+04] 190 4823 3.80
(1.23e+04,1.63e+04] 87 4910 1.74
(1.63e+04,2.04e+04] 47 4957 0.94
(2.04e+04,2.45e+04] 29 4986 0.58
(2.45e+04,2.86e+04] 7 4993 0.14
(2.86e+04,3.27e+04] 4 4997 0.08
(3.27e+04,3.68e+04] 3 5000 0.06
Total 5000 NA 100.00

La distribución del número de votos muestra que una gran parte de las películas recibe pocos votos, con más del 80% de las películas concentradas en los primeros intervalos, lo que sugiere que la mayoría de las películas no alcanzan un nivel alto de popularidad en términos de votos.

Medidas de Tendencia Central

# Función para calcular la moda
moda <- function(x) {
  uniq <- unique(na.omit(x))
  uniq[which.max(tabulate(match(x, uniq)))]
}

# Calcular media, moda y mediana para X.Worldwide
media_X.Worldwide <- mean(datos$X.Worldwide, na.rm = TRUE)
mediana_X.Worldwide <- median(datos$X.Worldwide, na.rm = TRUE)
moda_X.Worldwide <- moda(datos$X.Worldwide)

# Calcular media, moda y mediana para Domestic
media_Domestic <- mean(datos$Domestic, na.rm = TRUE)
mediana_Domestic <- median(datos$Domestic, na.rm = TRUE)
moda_Domestic <- moda(datos$Domestic)

# Calcular media, moda y mediana para Year
media_Year <- mean(datos$Year, na.rm = TRUE)
mediana_Year <- median(datos$Year, na.rm = TRUE)
moda_Year <- moda(datos$Year)

# Calcular media, moda y mediana para Foreign
media_Foreign <- mean(datos$Foreign, na.rm = TRUE)
mediana_Foreign <- median(datos$Foreign, na.rm = TRUE)
moda_Foreign <- moda(datos$Foreign)

# Calcular media, moda y mediana para Vote_Count
media_Vote_Count <- mean(datos$Vote_Count, na.rm = TRUE)
mediana_Vote_Count <- median(datos$Vote_Count, na.rm = TRUE)
moda_Vote_Count <- moda(datos$Vote_Count)

# Redondear las medias a 2 decimales y asegurarse de que no estén en notación científica
resultados <- data.frame(
  Variable = c("X.Worldwide", "Domestic", "Year", "Foreign", "Vote Count"),
  Media = c(
    format(media_X.Worldwide, scientific = FALSE, digits = 2), 
    format(media_Domestic, scientific = FALSE, digits = 2), 
    format(media_Year, scientific = FALSE, digits = 2), 
    format(media_Foreign, scientific = FALSE, digits = 2),
    format(media_Vote_Count, scientific = FALSE, digits = 2)
  ),
  Mediana = c(
    format(mediana_X.Worldwide, scientific = FALSE, digits = 2),
    format(mediana_Domestic, scientific = FALSE, digits = 2),
    format(mediana_Year, scientific = FALSE, digits = 2),
    format(mediana_Foreign, scientific = FALSE, digits = 2),
    format(mediana_Vote_Count, scientific = FALSE, digits = 2)
  ),
  Moda = c(moda_X.Worldwide, moda_Domestic, moda_Year, moda_Foreign, moda_Vote_Count)
)

# Mostrar la tabla utilizando kableExtra
library(kableExtra)

kable(resultados, col.names = c("Variable", "Media", "Mediana", "Moda")) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), full_width = F) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#4CAF50") %>%
  row_spec(1:5, background = "#f5f5f5")
Variable Media Mediana Moda
X.Worldwide 119213693 48446575 32800000.0
Domestic 36 37 0.0
Year 2012 2012 2000.0
Foreign 64 63 100.0
Vote Count 2481 1036 1035.5
  • Asimetría en la variable Worldwide

    • La media (11,921,3693) es significativamente mayor que la mediana (48,446,575) y la moda (32,800,000). Esto sugiere una distribución sesgada a la derecha (asimetría positiva), donde unos pocos valores muy altos están elevando la media.
  • La variable Year muestra una distribución sin sesgo

    • La media, mediana son iguales (2012, 2012), lo que indica que los valores están uniformemente distribuidos en torno a la media y que el año en que se grabaron más peliculas fue en el año 2000.
  • Vote Count tiene una distribución altamente sesgada

    • La media (2532) es mucho mayor que la mediana (1036), lo que sugiere un sesgo positivo. La moda es 0, lo que indica que el valor más común en los datos es 0, posiblemente porque muchas películas recibieron pocos votos o no fueron calificadas.

Medidas de Dispersión

# Calcular medidas de dispersión para X.Worldwide
rango_X.Worldwide <- range(datos$X.Worldwide, na.rm = TRUE)
varianza_X.Worldwide <- var(datos$X.Worldwide, na.rm = TRUE)
sd_X.Worldwide <- sd(datos$X.Worldwide, na.rm = TRUE)
cv_X.Worldwide <- sd_X.Worldwide / mean(datos$X.Worldwide, na.rm = TRUE)

# Calcular medidas de dispersión para Domestic
rango_Domestic <- range(datos$Domestic, na.rm = TRUE)
varianza_Domestic <- var(datos$Domestic, na.rm = TRUE)
sd_Domestic <- sd(datos$Domestic, na.rm = TRUE)
cv_Domestic <- sd_Domestic / mean(datos$Domestic, na.rm = TRUE)

# Calcular medidas de dispersión para Foreign
rango_Foreign <- range(datos$Foreign, na.rm = TRUE)
varianza_Foreign <- var(datos$Foreign, na.rm = TRUE)
sd_Foreign <- sd(datos$Foreign, na.rm = TRUE)
cv_Foreign <- sd_Foreign / mean(datos$Foreign, na.rm = TRUE)

# Calcular medidas de dispersión para Vote_Count
rango_Year <- range(datos$Vote_Count, na.rm = TRUE)
varianza_Year <- var(datos$Vote_Count, na.rm = TRUE)
sd_Year <- sd(datos$Vote_Count, na.rm = TRUE)
cv_Year <- sd_Year / mean(datos$Vote_Count, na.rm = TRUE)

# Crear el dataframe con todas las medidas
tabla_dispersion <- data.frame(
  Variable = c("X.Worldwide", "Domestic", "Foreign", "Vote Count"),
  Rango = c(paste(rango_X.Worldwide[1], "-", rango_X.Worldwide[2]),
            paste(rango_Domestic[1], "-", rango_Domestic[2]),
            paste(rango_Foreign[1], "-", rango_Foreign[2]),
            paste(rango_Year[1], "-", rango_Year[2])),
  Varianza = c(format(varianza_X.Worldwide, scientific = FALSE, digits = 4), 
                format(varianza_Domestic, scientific = FALSE, digits = 4), 
                format(varianza_Foreign, scientific = FALSE, digits = 4), 
                format(varianza_Year, scientific = FALSE, digits = 4)),
  `Desviación Estándar` = c(format(sd_X.Worldwide, scientific = FALSE, digits = 4), 
                             format(sd_Domestic, scientific = FALSE, digits = 4), 
                             format(sd_Foreign, scientific = FALSE, digits = 4), 
                             format(sd_Year, scientific = FALSE, digits = 4)),
  `Coeficiente de Variación` = c(format(cv_X.Worldwide, scientific = FALSE, digits = 4), 
                                   format(cv_Domestic, scientific = FALSE, digits = 4), 
                                   format(cv_Foreign, scientific = FALSE, digits = 4), 
                                   format(cv_Year, scientific = FALSE, digits = 4))
)

# Mostrar la tabla con kable
library(kableExtra)
tabla_dispersion %>%
  kbl(caption = "Medidas de Dispersión para Variables Cuantitativas", digits = 4, align = "c") %>%
  kable_styling(full_width = F, bootstrap_options = c("striped", "hover", "condensed"), 
                font_size = 12, position = "center") %>%
  column_spec(1, bold = TRUE, background = "lightblue")
Medidas de Dispersión para Variables Cuantitativas
Variable Rango Varianza Desviación.Estándar Coeficiente.de.Variación
X.Worldwide 1666028 - 2799439100 40210012222775640 200524343 1.682
Domestic 0 - 100 939.9 30.66 0.8578
Foreign 0 - 100 939.7 30.65 0.4771
Vote Count 0 - 36753 15117008 3888 1.567
  • Worldwide tiene el mayor rango, lo que indica una enorme variabilidad en la recaudación de las películas. Su varianza es extremadamente alta, lo que significa que los valores están muy dispersos con respecto a la media. La desviación estándar también es grande, reafirmando la alta variabilidad en los ingresos de las películas. Y el Coeficiente de variación indica que, en proporción a la media, hay una gran dispersión.

  • En Domestic el rango es más limitado, ya que probablemente esté en una escala porcentual. La varianza y desviación estándar son moderadas en comparación con la recaudación mundial. Por ultimo, el Coeficiente de variación sugiere que la dispersión en relación con la media es moderada.

  • Foreign parece ser una variable más estable en comparación con Domestic y X.Worldwide. Aunque la variabilidad absoluta es similar a Domestic, en términos relativos los ingresos internacionales muestran una menor dispersión, lo que sugiere una mayor consistencia en el rendimiento de las películas en mercados extranjeros.

  • Vote Count es una variable con altísima dispersión, lo que indica que la cantidad de votos está muy desbalanceada entre películas. Algunas reciben miles de valoraciones, mientras que otras casi ninguna. Esto sugiere una distribución desigual de la atención del público, lo cual es común en la industria del cine, donde ciertos títulos dominan el interés general.

Distribución de las variables cuantitativas

library(ggplot2)
library(reshape2)

# Crear un dataframe con solo las variables relevantes
datos_ingresos <- datos[, c("X.Worldwide", "X.Domestic", "X.Foreign")]

# Transformar los datos a formato largo para el boxplot
datos_largos_ingresos <- melt(datos_ingresos, variable.name = "Ingreso", value.name = "Valor")
## No id variables; using all as measure variables
# Crear el boxplot para los ingresos
ggplot(datos_largos_ingresos, aes(x = Ingreso, y = Valor)) +
  geom_boxplot() +
  labs(title = "Comparación de Ingresos de Taquilla",
       x = "Tipo de Ingreso",
       y = "Valor de Ingreso") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

library(ggplot2)

# Histograma de ingresos mundiales
ggplot(datos, aes(x = X.Worldwide)) + 
  geom_histogram(binwidth = 50000000, fill = "blue", color = "black") +
  labs(title = "Distribución de Ingresos Mundiales", x = "Ingresos Mundiales", y = "Frecuencia")

# Histograma de ingresos domésticos
ggplot(datos, aes(x = X.Domestic)) + 
  geom_histogram(binwidth = 50000000, fill = "green", color = "black") +
  labs(title = "Distribución de Ingresos Domésticos", x = "Ingresos Domésticos", y = "Frecuencia")

# Histograma de ingresos extranjeros
ggplot(datos, aes(x = X.Foreign)) + 
  geom_histogram(binwidth = 50000000, fill = "red", color = "black") +
  labs(title = "Distribución de Ingresos Extranjeros", x = "Ingresos Extranjeros", y = "Frecuencia")

Anotaciones:

  • Los histogramas de las variables Worldwide, Domestic y Foreign, revelan una distribución marcadamente asimétrica y alejada de la normalidad, caracterizada por un sesgo positivo. Esto significa que la mayoría de los datos se concentran en los valores más bajos, mientras que la cola de la distribución se extiende hacia la derecha, indicando la presencia de valores atípicamente altos. Además, a pesar de que podemos observar una distribución similar, vemos que el rango intercuartílico de la variable Worlwide en el diagrama de cajas y bigotes es un poco ancho, por lo cual podríamos concluir que los datos tienen una mayor variabilidad que Domestic y Foreign. Visualmente, es evidente que ninguna de las tres variables siguen una distribución normal; sin embargo, realizamosla prueba de normalidad de Anderson-Darling para verificarlo:
library(nortest)

# Prueba de Anderson-Darling para las tres variables
ad_worldwide <- ad.test(datos$X.Worldwide)
ad_foreign <- ad.test(datos$X.Foreign)
ad_domestic <- ad.test(datos$X.Domestic)

ad_worldwide
## 
##  Anderson-Darling normality test
## 
## data:  datos$X.Worldwide
## A = 706.49, p-value < 2.2e-16
ad_foreign
## 
##  Anderson-Darling normality test
## 
## data:  datos$X.Foreign
## A = 743.17, p-value < 2.2e-16
ad_domestic
## 
##  Anderson-Darling normality test
## 
## data:  datos$X.Domestic
## A = 564.58, p-value < 2.2e-16
  • En Worlwide, Foreign y Domestic observamos que el p-valor es menor que 0.05, por lo tanto tenemos suficiente evidencia para rechazar la hipótesis nula de que los datos siguen una distribución normal, por lo que podemos afirmar que no son normales.
datos_porcentajes <- datos[, c("Domestic..", "Foreign..")]
datos_largos_porcentajes <- melt(datos_porcentajes, variable.name = "Porcentaje", value.name = "Valor")
## No id variables; using all as measure variables
ggplot(datos_largos_porcentajes, aes(x = Porcentaje, y = Valor)) +
  geom_boxplot() +
  labs(title = "Comparación de Porcentajes de Ingresos de Taquilla",
       x = "Tipo de Porcentaje",
       y = "Porcentaje de Ingresos") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

library(reshape2)

# Seleccionar las variables y transformarlas a formato largo
datos_porcentajes <- datos[, c("Domestic..", "Foreign..")]
datos_largos <- melt(datos_porcentajes, variable.name = "Tipo", value.name = "Valor")
## No id variables; using all as measure variables
# Crear un histograma comparativo
ggplot(datos_largos, aes(x = Valor, fill = Tipo)) +
  geom_histogram(position = "identity", alpha = 0.5, bins = 30) +
  labs(title = "Comparación de Domestic % y Foreign %",
       x = "Porcentaje",
       y = "Frecuencia") +
  theme_minimal()

Anotaciones:

  • Los histogramas y los boxplots de las variables Domestic % y Foreign %, revelan una distribución marcadamente asimétrica y alejada de la normalidad, Domestic % cuenta con un sesgo positivo, lo que nos indica que la mayoría de las películas generan bajos porcentajes de sus ingresos en el mercado doméstico, pero algunas excepciones logran recaudar una gran parte localmente, lo que explicaría que la cola de la distribución se extienda hacia la derecha, indicando la presencia de valores atípicamente altos.

  • Por otro lado, Foreign % tiene un sesgo negativo o a la izquierda, lo que nos da a entender que la mayoría de las películas obtienen una gran parte de sus ingresos en mercados internacionales, es decir, dependen de los ingresos extranjeros para alcanzar grandes cifras en taquilla. Los boxplots también nos evidencian que la mediana de Foreign % es mayor, confirmando que esta tiene valores típicamente mayores a Domestic % y se complementan, puesto que si una sube, la otra baja.

En conclusión, estos resultados sugieren que el éxito global de una película está más determinado por su desempeño en mercados extranejeros

En otro orden de ideas, es evidente que estas variables no siguen una distribución normal; sin embargo, realizaremos la prueba de normalidad de Anderson-Darling para verificarlo:

library(nortest)

# Prueba de Anderson-Darling para las tres variables
ad_foreignp <- ad.test(datos$Foreign)
ad_domesticp <- ad.test(datos$Domestic)

ad_foreignp
## 
##  Anderson-Darling normality test
## 
## data:  datos$Foreign
## A = 146.83, p-value < 2.2e-16
ad_domesticp
## 
##  Anderson-Darling normality test
## 
## data:  datos$Domestic
## A = 146.99, p-value < 2.2e-16
  • En Foreign % y Domestic % observamos que el p-valor es menor que 0.05, por lo tanto tenemos suficiente evidencia para rechazar la hipótesis nula de que los datos siguen una distribución normal, por lo que podemos afirmar que no son normales.
library(ggplot2)

datos$Rating <- as.numeric(gsub("/10", "", datos$Rating))

ggplot(datos, aes(y = Rating)) +
  geom_boxplot() +
  labs(title = "Boxplot de Rating",
       x = "Rating",
       y = "Valor de Rating") +
  theme_minimal()
## Warning: Removed 170 rows containing non-finite outside the scale range
## (`stat_boxplot()`).

ggplot(datos, aes(x = Rating)) +
  geom_histogram(binwidth = 0.2, fill = "skyblue", color = "black", alpha = 0.7) +
  labs(title = "Histograma de Rating",
       x = "Rating (Calificación Media)",
       y = "Frecuencia") +
  theme_minimal()
## Warning: Removed 170 rows containing non-finite outside the scale range
## (`stat_bin()`).

  • El histograma de la variable Rating, muestra una ligera asimetría negativa o sesgo a la izquierda. La mayor concentración de datos está entre 6 y 8, con la moda cercana a 7. Sin embargo, también se observa en el boxplot que la cola de la distribución se extiende hacia valores más bajos, acercándose a 0, lo que indica la presencia de algunas calificaciones mucho menores pero con poca frecuencia. Este tipo de distribución sugiere que la mayoría de las calificaciones son relativamente altas y que hay pocos valores extremadamente bajos. Desde otro punto de vista, la caja es angosta, lo que implica una menor variabilidad en los datos, lo cual se ve en el histograma, puesto que los datos están mas concentrados. A pesar de esto, la vista nos dice que esta variable no sigue una distribución normal; sin embargo, realizaremos la prueba de normalidad de Anderson-Darling para verificarlo:
library(nortest)
datos$Rating <- as.numeric(gsub("/10", "", datos$Rating))

ad_rating <- ad.test(datos$Rating)

ad_rating
## 
##  Anderson-Darling normality test
## 
## data:  datos$Rating
## A = 45.239, p-value < 2.2e-16
  • En Rating observamos que el p-valor es menor que 0.05, por lo tanto tenemos suficiente evidencia para rechazar la hipótesis nula de que los datos siguen una distribución normal, por lo que podemos afirmar que no son normales.

¿Existen diferencias estadísticamente significativas entre los valores medios de las ganancias internacionales de las películas según su género?

En este punto, evaluaremos si el género de una película influye directamente en las ganancias internacionales obtenidas. Para ello, nos centraremos en tres géneros específicos y analizaremos si las medias de sus ganancias internacionales presentan diferencias significativas.

Usaremos como grupo de interés la variable “Género” y “Foreign” para determinar las ganancias internacionales de cada película.

Antes de aplicar las pruebas estadísticas, evaluaremos la distribución de los datos para determinar si se ajustan a una distribución normal. Esto es crucial porque la normalidad de los datos guiará la elección de la prueba estadística adecuada (paramétrica o no paramétrica).

Como ya se comprobó antes, la variable Foreign no cumple el supuesto de normalidad, por lo cual utilizaremos la prueba de Kruskal-Wallis en lugar de la prueba de ANOVA, ya que la primera es una alternativa no paramétrica que no requiere que los datos sigan una distribución normal.

Primero realizaré una filtración de los géneros de las películas, puesto que se encuentran juntas entre comas.

#Separamos los géneros
Generos_Separados <- unlist(strsplit(as.character(datos$Genres), split = ", "))

#Contamos cuantas películas hay
Frecuencia_Absoluta <- table(Generos_Separados)

#Calculamos la frecuencia relativa
Frecuencia_Relativa <- prop.table(Frecuencia_Absoluta)

#Agrupamos todo en Data Frame
Tabla_Final <- data.frame(Genero = names(Frecuencia_Absoluta), Frecuencia_Absoluta = as.numeric(Frecuencia_Absoluta), Frecuencia_Relativa = round(100 * as.numeric(Frecuencia_Relativa), 2)) #Multiplicamos por 100 para convertilo en porcentaje y lo redondeamos a dos cifras.

colnames(Tabla_Final)[colnames(Tabla_Final) == "Frecuencia_Absoluta"] <- "Frecuencia Absoluta"
colnames(Tabla_Final)[colnames(Tabla_Final) == "Frecuencia_Relativa"] <- "Frecuencia Relativa"

#Hacemos una tabla con la función "kable"
Tabla_Frecuencia <- kable(Tabla_Final, align = "c") %>%  
  kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), 
                font_size = 15, fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, width = "10em") %>%   
  column_spec(2, width = "10em") %>%                
  column_spec(3, width = "10em") %>%                
  row_spec(0, bold = TRUE, background = "#9eb5d9", color = "black")

Tabla_Frecuencia
Genero Frecuencia Absoluta Frecuencia Relativa
Action 1384 10.74
Adventure 1063 8.25
Animation 498 3.87
Comedy 1907 14.80
Crime 699 5.43
Documentary 79 0.61
Drama 2009 15.60
Family 694 5.39
Fantasy 634 4.92
History 293 2.27
Horror 436 3.38
Music 152 1.18
Mystery 431 3.35
Romance 844 6.55
Science Fiction 514 3.99
Thriller 1060 8.23
TV Movie 7 0.05
War 144 1.12
Western 34 0.26

Como podemos ver, ya hemos separado los géneros de las películas, lo que nos permitirá contar cuántas películas corresponden a cada género. A continuación, nos enfocaremos en el otro grupo de interés, que son las ganancias internacionales de las películas. Para ello, procederemos a filtrar las películas según su género y analizaremos las ganancias correspondientes a cada grupo.

GananciasGenero <- rep(datos$X.Foreign, sapply(strsplit(as.character(datos$Genres), split = ", "), length))

#Juntamos los géneros y las ganancias de las películas en un Data Frame
Data_Frame_Ganancias_Generos <- data.frame(Genero = Generos_Separados, Ganancias = GananciasGenero)

#Las agrupamos por genero
Agrupacion_Ganancias_Generos <- aggregate(Ganancias ~ Genero, data = Data_Frame_Ganancias_Generos, sum)


# Formateamos las ganancias con puntos y comas para la tabla
Agrupacion_Ganancias_Generos$Ganancias_formateadas <- comma(Agrupacion_Ganancias_Generos$Ganancias)

colnames(Agrupacion_Ganancias_Generos)[colnames(Agrupacion_Ganancias_Generos) == "Ganancias_formateadas"] <- "Ganancia"

# Creamos la tabla con la columna de ganancias formateadas
Tabla_Frecuencia3 <- kable(Agrupacion_Ganancias_Generos[, c("Genero", "Ganancia")], 
                            caption = "Tabla: Ganancias Totales por Genero", align = "c") %>%  
  kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), 
                font_size = 15, fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, width = "10em") %>%   
  column_spec(2, width = "10em") %>%                
  row_spec(0, bold = TRUE, background = "#00b08e", color = "black")

# Mostrar la tabla
Tabla_Frecuencia3
Tabla: Ganancias Totales por Genero
Genero Ganancia
Action 165,951,686,864
Adventure 168,387,139,689
Animation 61,501,072,956
Comedy 120,154,492,707
Crime 40,170,061,703
Documentary 1,827,471,543
Drama 102,252,519,801
Family 75,375,365,889
Fantasy 81,244,594,839
History 16,554,412,413
Horror 20,272,217,062
Music 8,148,949,877
Mystery 23,721,062,500
Romance 42,095,656,530
Science Fiction 82,247,553,450
Thriller 72,920,927,337
TV Movie 129,380,542
War 12,760,889,331
Western 1,913,719,532
# Crear gráfico de barras con las ganancias numéricas, pero con etiquetas formateadas
ggplot(Agrupacion_Ganancias_Generos, aes(x = reorder(Genero, -Ganancias), y = Ganancias, fill = Genero)) + 
  geom_bar(stat = "identity") +
  labs(title = "Ganancias Totales por Genero", x = "Genero", y = "Ganancia Total") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_y_continuous(labels = scales::comma)  # Formateamos las etiquetas del eje Y con puntos y comas

De acuerdo con la tabla, podemos observar que los géneros comedia, acción y aventura son los que generaron mayores ganancias. Por lo tanto, nos centraremos en estos tres géneros. A simple vista, podríamos suponer que el género que más generó será el que tenga la mediana más alta. Vamos a comprobar esta hipótesis calculando la media y la mediana de las ganancias para cada género:

# Filtrar los géneros en los que estamos interesados
Generos_Seleccionados <- c("Action", "Adventure", "Comedy")

# Filtrar los datos que contienen esos géneros
Data_Filtrada <- subset(Data_Frame_Ganancias_Generos, Genero %in% Generos_Seleccionados)
# Calcular la media y la mediana de las ganancias por género
Estadisticas_Ganancias_Filtradas <- aggregate(Ganancias ~ Genero, data = Data_Filtrada, 
                                              FUN = function(x) c(Mediana = median(x, na.rm = TRUE)))

# Convertir la matriz de estadísticas en columnas separadas
Estadisticas_Ganancias_Filtradas <- data.frame(Genero = Estadisticas_Ganancias_Filtradas$Genero, 
                                               Medianas = Estadisticas_Ganancias_Filtradas$Ganancias)

# Formatear los valores con comas
Estadisticas_Ganancias_Filtradas$Mediana <- comma(Estadisticas_Ganancias_Filtradas$Medianas)

# Crear la tabla con kable
Tabla_Estadisticas_Filtradas <- kable(Estadisticas_Ganancias_Filtradas[, c("Genero", "Mediana")], 
                                      caption = "Tabla: Mediana de Ganancias (Action, Adventure, Comedy)", 
                                      align = "c") %>%  
  kable_styling(full_width = TRUE, bootstrap_options = c("striped", "hover", "condensed", "responsive"), 
                font_size = 15, fixed_thead = TRUE) %>%
  column_spec(1, bold = TRUE, width = "10em") %>%   
  column_spec(2, width = "10em") %>%                
  row_spec(0, bold = TRUE, background = "#ffcc00", color = "black")

# Mostrar la tabla
Tabla_Estadisticas_Filtradas
Tabla: Mediana de Ganancias (Action, Adventure, Comedy)
Genero Mediana
Action 48,478,541
Adventure 61,153,455
Comedy 27,302,268
# Gráfico de barras para la mediana de ganancias
ggplot(Estadisticas_Ganancias_Filtradas, aes(x = reorder(Genero, -Medianas), y = Medianas, fill = Genero)) + 
  geom_bar(stat = "identity") +
  labs(title = "Mediana de Ganancias por Género", x = "Género", y = "Mediana de Ganancia") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_y_continuous(labels = scales::comma)

Como podemos observar, la mediana se sigue acomodando a los indicios que obtuvimos antes. Sin embargo, veamos si esta diferencia en las distribuciones (o en las medianas) es en realidad significativa con la prueba de Kruskal.

# Filtrar los géneros en los que estamos interesados
Generos_Seleccionados <- c("Action", "Adventure", "Comedy")

# Filtrar los datos que contienen esos géneros
Data_Filtrada <- subset(Data_Frame_Ganancias_Generos, Genero %in% Generos_Seleccionados)
# Realizar la prueba de Kruskal-Wallis
kruskal_test <- kruskal.test(Ganancias ~ Genero, data = Data_Filtrada)


kruskal_test
## 
##  Kruskal-Wallis rank sum test
## 
## data:  Ganancias by Genero
## Kruskal-Wallis chi-squared = 310.49, df = 2, p-value < 2.2e-16

El valor p obtenido es menor que 0.05, lo que nos lleva a rechazar la hipótesis nula. Esto indica que existen diferencias significativas entre las medianas de los géneros de películas (acción, comedia y aventura) en cuanto a sus ganancias internacionales. En consecuencia, podemos concluir que las ganancias internacionales varían de manera significativa según el género de la película.

# Realizar la prueba de Dunn
dunn_result <- dunn.test(Data_Filtrada$Ganancias, Data_Filtrada$Genero, 
                         kw = TRUE, label = TRUE, list = TRUE)
##   Kruskal-Wallis rank sum test
## 
## data: x and group
## Kruskal-Wallis chi-squared = 310.4948, df = 2, p-value = 0
## 
## 
##                            Comparison of x by group                            
##                                 (No adjustment)                                
## Col Mean-|
## Row Mean |     Action   Adventur
## ---------+----------------------
## Adventur |  -3.592213
##          |    0.0002*
##          |
##   Comedy |   13.12019   15.93132
##          |    0.0000*    0.0000*
## 
## 
## List of pairwise comparisons: Z statistic (p-value)
## ----------------------------------------
## Action - Adventure : -3.592213 (0.0002)*
## Action - Comedy    :  13.12019 (0.0000)*
## Adventure - Comedy :  15.93132 (0.0000)*
## 
## alpha = 0.05
## Reject Ho if p <= alpha/2
# Mostrar el resultado de la prueba
dunn_result
## $chi2
## [1] 310.4948
## 
## $Z
## [1] -3.592214 13.120198 15.931321
## 
## $P
## [1] 1.639405e-04 1.261376e-39 1.920784e-57
## 
## $P.adjusted
## [1] 1.639405e-04 1.261376e-39 1.920784e-57
## 
## $comparisons
## [1] "Action - Adventure" "Action - Comedy"    "Adventure - Comedy"

Como vemos, la p adquiere un valor menor a 0.05 para todos los géneros. Lo que nos lleva a la conclusión de que todos son diferentes entre sí.

Conclusión

De acuerdo a todo lo anterior, podemos destacar las siguientes conclusiones:

  • Media y Mediana:
    Aunque en algunos casos calcular solo la media y la mediana no es suficiente para determinar si existe una diferencia significativa entre los grupos, en este análisis vimos que ambos indicadores nos señalaron la presencia de diferencias significativas entre los tres géneros de películas seleccionados.

  • Prueba de Kruskal:
    La prueba de Kruskal nos permitió verificar que la distribución es diferente en todos los géneros comparados, indicando que existe una diferencia significativa en las ganancias internacionales entre los géneros de películas de acción, comedia y aventura.

  • Rendimiento de los Géneros:
    Es interesante observar que, aunque el género de comedia tuvo más películas que el género de acción, la prueba de Kruskal mostró que existía una diferencia significativa entre ambos. Esto nos lleva a inferir que, a pesar de que las películas de acción eran menos en número, su rendimiento fue superior, lo que sugiere que estaban mejor valoradas (Rating) y, por lo tanto, generaban más dinero. Además, se podría decir que la diferencia no fue producto del azar, lo que nos permite concluir que el género puede llegar a tener un impacto en las ganancias internacionales de las películas.

Expansión y Transformación del Cine en el Mundo en el siglo XXI

Comparativa por volumen de producción

A continuación se desea hacer una comparativa del volumen de producción de peliculas por país divido en 3 intervalos. De 2000 a 2009, de 2010 a 2019 y 2020 en adelante. El objetivo es analizar cambios en los niveles de producción en distintos paises y analizar un posible crecimiento o decrecimento en los mismos.

df_paises$Production_Countries <- trimws(df_paises$Production_Countries)
df_paises_con_year <- datos %>%
  filter(!is.na(Production_Countries)) %>%
  mutate(Production_Countries = trimws(Production_Countries)) %>%
  separate_rows(Production_Countries, sep = ", ") %>%
  group_by(Production_Countries, Year) %>%
  summarise(Numero_Peliculas = n()) %>%
  ungroup()
## `summarise()` has grouped output by 'Production_Countries'. You can override
## using the `.groups` argument.
produccion_pais <- df_paises_con_year %>%
  filter(Year >= 2000 & Year <= 2009) %>%
  group_by(Production_Countries) %>%
  summarise(Total_Peliculas = sum(Numero_Peliculas))


mapa <- joinCountryData2Map(produccion_pais, joinCode = "NAME", nameJoinColumn = "Production_Countries")
## 56 codes from your data successfully matched countries in the map
## 2 codes from your data failed to match with a country code in the map
## 187 codes from the map weren't represented in your data
mapCountryData(mapa, nameColumnToPlot = "Total_Peliculas", 
               catMethod = "fixedWidth", mapTitle = "Volumen de Películas por País", 
               colourPalette = "terrain")

Comparativa por volumen de producción (Excluyendo a USA) desde 2000 a 2009

produccion_pais <- df_paises_con_year %>%
  filter(Year >= 2000 & Year <= 2009 & Production_Countries != 'United States of America') %>%
  group_by(Production_Countries) %>%
  summarise(Total_Peliculas = sum(Numero_Peliculas))

mapa <- joinCountryData2Map(produccion_pais, joinCode = "NAME", nameJoinColumn = "Production_Countries")
## 55 codes from your data successfully matched countries in the map
## 2 codes from your data failed to match with a country code in the map
## 188 codes from the map weren't represented in your data
mapCountryData(mapa, nameColumnToPlot = "Total_Peliculas", 
               catMethod = "fixedWidth", mapTitle = "Volumen de Películas por País", 
               colourPalette = "terrain")

Si analizamos detenidamente los gráficos anteriores podemos notar que el volumen de producción de Estados Unidos destaca enormemente generando una disminución en la visibilidad de los demás países. Dado a que el objetivo es tener una visión equilibrada entre los todos países, se decidió excluir a Estados Unidos de las demás comparativas para poder destacar a los demás lugares que han tenido una participación proporcionalmente menor en la industria cinematográfica mundial.

Comparativa por volumen de producción (Excluyendo a USA) desde 2010 a 2019

produccion_pais <- df_paises_con_year %>%
  filter(Year >= 2010 & Year <= 2019 & Production_Countries != 'United States of America') %>%
  group_by(Production_Countries) %>%
  summarise(Total_Peliculas = sum(Numero_Peliculas))

mapa <- joinCountryData2Map(produccion_pais, joinCode = "NAME", nameJoinColumn = "Production_Countries")
## 55 codes from your data successfully matched countries in the map
## 2 codes from your data failed to match with a country code in the map
## 188 codes from the map weren't represented in your data
mapCountryData(mapa, nameColumnToPlot = "Total_Peliculas", 
               catMethod = "fixedWidth", mapTitle = "Volumen de Películas por País", 
               colourPalette = "terrain")

Comparativa por volumen de producción (Excluyendo a USA) desde 2020

produccion_pais <- df_paises_con_year %>%
  filter(Year >= 2020 & Production_Countries != 'United States of America') %>%
  group_by(Production_Countries) %>%
  summarise(Total_Peliculas = sum(Numero_Peliculas))

mapa <- joinCountryData2Map(produccion_pais, joinCode = "NAME", nameJoinColumn = "Production_Countries")
## 55 codes from your data successfully matched countries in the map
## 1 codes from your data failed to match with a country code in the map
## 188 codes from the map weren't represented in your data
mapCountryData(mapa, nameColumnToPlot = "Total_Peliculas", 
               catMethod = "fixedWidth", mapTitle = "Volumen de Películas por País", 
               colourPalette = "terrain")

Los gráficos anteriores permiten hacer un análisis interesante sobre el crecimiento de la producción de películas en el continente asiático. Se ve a inicios de los 2000 que los paises con mayor presencia en este continente eran Japón y Corea del Sur. En esa época se destacaba más Europa como centro de la producción de entretenimiento, sin embargo en la década de 2010 a 2019 vemos un crecimiento notable en países como India y China. A inicios de la década 2020 - presente se ve una concentración en Japón como el país con mayor volumen de películas en la industria.

Comparativa de los ingresos

Ingreso medio por país desde el año 2000 a 2009

df_paises_con_year <- datos %>%
  filter(!is.na(Production_Countries), !is.na(`X.Worldwide`)) %>%
  mutate(Production_Countries = trimws(Production_Countries)) %>%
  separate_rows(Production_Countries, sep = ", ") %>%
  group_by(Production_Countries, Year) %>%
  summarise(Ingreso_Medio = mean(`X.Worldwide`, na.rm = TRUE)) %>%
  ungroup()
## `summarise()` has grouped output by 'Production_Countries'. You can override
## using the `.groups` argument.
ingresos_pais <- df_paises_con_year %>%
    filter(Year >= 2000 & Year <= 2009) %>%
  group_by(Production_Countries) %>%
  summarise(Ingreso_Medio = mean(Ingreso_Medio, na.rm = TRUE))


ingresos_pais$Production_Countries <- trimws(ingresos_pais$Production_Countries)

mapa <- joinCountryData2Map(ingresos_pais, 
                            joinCode = "NAME", 
                            nameJoinColumn = "Production_Countries")
## 56 codes from your data successfully matched countries in the map
## 2 codes from your data failed to match with a country code in the map
## 187 codes from the map weren't represented in your data
mapCountryData(mapa, 
               nameColumnToPlot = "Ingreso_Medio", 
               catMethod = "log", 
               mapTitle = "Ingreso Medio por País de Producción (2000-2009)", 
               colourPalette = "heat")
## Warning in rwmGetClassBreaks(dataCategorised, catMethod = catMethod, numCats = numCats, : classification method should be set to one of :fixedWidth diverging quantiles pretty logFixedWidth categorical 
## setting to fixedWidth as default

¿Por qué New Zealand lidera en este aspecto?

df_paises_con_title <- datos %>%
  filter(!is.na(Production_Countries)) %>%
  mutate(Production_Countries = trimws(Production_Countries)) %>%
  separate_rows(Production_Countries, sep = ", ") %>%
  filter(Production_Countries == "New Zealand") %>%
  group_by(Production_Countries, `Release.Group`) %>%
  summarise(Titles = (`Release.Group`), .groups = 'drop') 

df_paises_con_title %>%
  select(Production_Countries, `Release.Group`) %>%
  kable("html", caption = "Películas de Nueva Zelanda por Grupo de Lanzamiento") %>%
  kable_styling(
    full_width = FALSE,
    position = "center",
    font_size = 12,
  ) %>%
  row_spec(0, bold = TRUE) %>%  # Aplica negrita en la fila de encabezados
  column_spec(1, bold = TRUE, background = "#f7f7f7") %>%
  column_spec(2, background = "#e9f5f5") %>%
  scroll_box(width = "100%", height = "100%")
Películas de Nueva Zelanda por Grupo de Lanzamiento
Production_Countries Release.Group
New Zealand 10,000 BC
New Zealand 30 Days of Night
New Zealand Boy
New Zealand District 9
New Zealand Evil Dead Rise
New Zealand Jojo Rabbit
New Zealand King Kong
New Zealand Mortal Engines
New Zealand Next Goal Wins
New Zealand The Adventures of Tintin
New Zealand The Hobbit: An Unexpected Journey
New Zealand The Hobbit: The Battle of the Five Armies
New Zealand The Hobbit: The Desolation of Smaug
New Zealand The Last Samurai
New Zealand The Lord of the Rings: The Fellowship of the Ring
New Zealand The Lord of the Rings: The Return of the King
New Zealand The Lord of the Rings: The Two Towers
New Zealand The Lord of the Rings: The War of the Rohirrim
New Zealand The Lovely Bones
New Zealand The World’s Fastest Indian
New Zealand Whale Rider
New Zealand Yogi Bear

Aquí ocurre algo interesante, New Zealand no es el país que más destaca a nivel mundial por su participación en la industria. Sin embargo, ha sido hogar de importantes y reconocidas sagas como el Señor de los anillos y el Hobbit. La combinación de un numero pequeño de peliculas pero de gran éxito mundial hace que se pueda mantener un promedio alto de ingresos para la industria.

Ingreso medio por país desde el año 2010 a 2019

ingresos_pais <- df_paises_con_year %>%
    filter(Year >= 2010 & Year <= 2019) %>%
  group_by(Production_Countries) %>%
  summarise(Ingreso_Medio = mean(Ingreso_Medio, na.rm = TRUE))

# Ahora el mapa
mapa <- joinCountryData2Map(ingresos_pais, 
                           joinCode = "NAME", 
                           nameJoinColumn = "Production_Countries")
## 56 codes from your data successfully matched countries in the map
## 2 codes from your data failed to match with a country code in the map
## 187 codes from the map weren't represented in your data
mapCountryData(mapa, 
              nameColumnToPlot = "Ingreso_Medio", 
              catMethod = "log", 
              mapTitle = "Ingreso medio por País de Producción", 
              colourPalette = "heat")
## Warning in rwmGetClassBreaks(dataCategorised, catMethod = catMethod, numCats = numCats, : classification method should be set to one of :fixedWidth diverging quantiles pretty logFixedWidth categorical 
## setting to fixedWidth as default

Ingreso medio por país a partir del año 2020

ingresos_pais <- df_paises_con_year %>%
    filter(Year >= 2020) %>%
  group_by(Production_Countries) %>%
  summarise(Ingreso_Medio = mean(Ingreso_Medio, na.rm = TRUE))

# Ahora el mapa
mapa <- joinCountryData2Map(ingresos_pais, 
                           joinCode = "NAME", 
                           nameJoinColumn = "Production_Countries")
## 56 codes from your data successfully matched countries in the map
## 1 codes from your data failed to match with a country code in the map
## 187 codes from the map weren't represented in your data
mapCountryData(mapa, 
              nameColumnToPlot = "Ingreso_Medio", 
              catMethod = "log", 
              mapTitle = "Ingreso medio por País de Producción", 
              colourPalette = "heat")
## Warning in rwmGetClassBreaks(dataCategorised, catMethod = catMethod, numCats = numCats, : classification method should be set to one of :fixedWidth diverging quantiles pretty logFixedWidth categorical 
## setting to fixedWidth as default

En esta comparativa ocurre algo interesante. Si bien se nota en la gráfica anterior, Japón es el país líder en la producción de películas (excluyendo a USA), sin embargo, no es el país con el ingreso medio más alto en sus producciones. Si se analiza detenidamente, se puede notar que en la primera década México, Rusia, India, Corea del Sur y varios países de Europa lideran en esta comparativa, sin embargo con el paso de los años, el ingreso medio más alto se concentra en China, que tambien se destaca como uno de los paises con mayor producción a nivel mundial de películas.

Evolución histórica de peliculas por idioma.

# Filtrar los datos por los idiomas seleccionados
datos_filtrados_idiomas <- datos %>%
  filter(Original_Language %in% c("en", "ja", "zh", "fr", "ko"))

# Gráfico de comparación de ingresos internacionales por idioma
ggplot(datos_filtrados_idiomas, 
       aes(x = Year, color = Original_Language, group = Original_Language)) +
  geom_point(stat = "count", size = 3) +  # Puntos
  geom_line(stat = "count", size = 1) +   # Líneas
  labs(title = "Evolución de la Producción de Películas por Idioma", 
       x = "Año", y = "Cantidad de Películas") +
  theme_minimal() +
  scale_color_manual(values = c("en" = "blue", "ja" = "red", "zh" = "green", "fr" = "purple", "ko" = "orange"))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

El resultado obtenido luego de comparar el volumen de producción a lo largo de la historia no sorprende. De forma indiscutible, el inglés domina en la escena mundial. Lo anterior tiene sentido teniendo en cuenta que es el país que más produce peliculas en el mundo. Luego, representando a Asia y Europa, siguen el japonés, mandarín, frances y coreano, con números bastante similares.

HALLAZGOS E INTERPRETACIONES

A lo largo del análisis exploratorio de datos (EDA), se examinaron diversas características de las películas con el objetivo de identificar patrones en su distribución según género, idioma original y país de producción. Se observan tendencias claras en la industria cinematográfica a lo largo de los años 2000 a 2024:

Factores que influyen en el éxito financiero de las películas
País de origen y volumen de producción:
- Estados Unidos domina ampliamente la producción de películas a nivel mundial, lo que explica su presencia constante en las películas con mayor recaudación. Al excluir a EE.UU., se observa una distribución más equilibrada, con Japón, China e India emergiendo como centros de producción clave en sus respectivas regiones. Un caso interesante es Nueva Zelanda, que, a pesar de producir pocas películas, ha sido el hogar de grandes éxitos como El Señor de los Anillos y El Hobbit, lo que demuestra que la cantidad de películas producidas no siempre se correlaciona directamente con el éxito financiero.

Recaudación y rentabilidad por país:
- Si bien Japón lidera la producción de películas en Asia, no es el país con el mayor ingreso medio por película. Durante la primera década de los 2000, países como México, Rusia, India y Corea del Sur mostraron altos ingresos promedio en sus producciones. A partir de la década de 2010, China ha aumentado su presencia tanto en términos de volumen de producción como en recaudación promedio, consolidándose como un actor clave en la industria.

Influencia del idioma en la recaudación:
- No sorprende que el inglés sea el idioma dominante en la industria cinematográfica, dado el volumen de producción de Hollywood y su influencia global. Sin embargo, otros idiomas como el japonés, mandarín, francés y coreano han mantenido una presencia estable en la industria, reflejando la importancia de los mercados regionales y la expansión del cine asiático y europeo.

Se ha identificado un cambio significativo en la producción y recaudación de películas a lo largo de los años. Mientras que en los primeros años del siglo XXI la industria cinematográfica estaba dominada por Estados Unidos y Europa, a partir de la década de 2010 se observa un crecimiento notable de Asia, con China y Japón tomando un papel protagonista. La industria cinematográfica ha pasado de estar centralizada en Hollywood a una distribución más diversificada, donde el cine asiático y de otros países ha logrado captar una mayor audiencia global.

El análisis confirma que la industria cinematográfica tiene una distribución desigual, con una fuerte concentración de películas en ciertos géneros, idiomas y países. Esto tiene implicaciones importantes para la diversidad del contenido disponible, el acceso de producciones de otros países a mercados internacionales y el impacto cultural de las películas en la audiencia global. Dado que el objetivo era explorar las principales características de las películas en términos de producción y distribución, podemos concluir que existe un claro predominio del cine angloparlante, con el género Drama como el más recurrente. Estos hallazgos pueden ser útiles para comprender tendencias de la industria y para futuras investigaciones sobre el impacto de estos factores en la taquilla y el consumo del público.