Problem Statement

Business Problem:

Amazon studios has continued to increase its portfolio of films and tv shows tied to its streaming platform. As such, Amazon is wanting an analysis performed on the IMDb metadata and the average reviews given to films to determine if box office success can be linked varying factors. The questions being asked are:

  • Do certain directors have higher movie reviews/monetary success than others?
  • Do certain genres of movies have higher movie reviews/monetary success?
  • Do specific movie genres and director combinations have better movie reviews/monetary success?

The primary variable being studied will be the film’s revenue. There are numerous factors that play into a films overall profit such as domestic, international, and Chinese box offices along with marketing budgets, etc. However, this data was not provided by IMDb and thus the revenue will be the primary variable studied.

Methodology

The below methodology was executed as follows:

  1. Identified any missing/null values within the data set
  2. For missing data (such as revenue) used the following methods:
    1. Used an A.I. platform such as ChatGPT to gather the missing information for the film (such as revenue and budget). This was done by using ChatGPT to write python code that utilized an API from https://www.omdbapi.com/ to pull in the director for each film into the data set.
  3. Created visualizations to compare variables with the target variable:
    1. Revenue per film/director
    2. Avg. Review per film/director
    3. Movie genres compared with revenue
    4. Various other trends and outliers were explored through data visualization
  4. Created models for target variable where applicable:
    1. Linear regression with revenue being the target variable
    2. Linear spline in an attempt to use scaled data to achieve a smoother regression
    3. Decision tree to determine most influential variables
    4. Clustering analysis
    5. Relative weight analysis
    6. Generalized additive model to determine if other variables are linearly related to the target variable

More models were explored in an attempt to provide the best possible outcome with the provided data.

Data Source

The raw data was gathered from Kaggle, and contained over 40,000 rows of data involving movies tied in with the IMDb database. https://www.kaggle.com/datasets/rounakbanik/the-movies-dataset. The data contains movies ranging from late 1800’s to 2018.

Insights

Below is a list of interesting insights throughout the analysis:

  • Genres were mostly not statistically significant except for a few exceptions: Action, Crime, Drama, Fantasy, Music, Mystery, Thriller, War, and Western. These genres seemed to have more impact in influencing Revenue than any other genre listed according to the first iteration of linear regression.
  • Regression 2 and 3 had similar results, but regression 3 had a better fit with budget, popularity, and vote average to be the most statistically significant variables.
  • Based on results from the decision tree model, higher budget films do not always indicate as being the most popular, but fall within the average for popularity.
  • See below for the analysis from the cluster model:
    • Cluster 1 (High Budget, High Popularity): This cluster likely represents blockbuster movies with significant investment and high audience engagement. Strategies for these films may involve heavy marketing campaigns and wide releases.
    • Cluster 2 (Low Budget, Low Popularity): Represents independent or lower-budget films that might have limited appeal. These might require targeted marketing strategies or niche audience engagement.
    • Cluster 3 (Moderate across metrics): Films that do not excel in any particular area but perform decently across the board. Strategies here might focus on leveraging moderate popularity to increase visibility or pairing with similar movies to enhance viewer recommendations.
  • Over time, action and adventure genres show a much higher average revenue in recent years (2010 - 2018) than other genres. Fantasy is a close second, but isn’t as common of a genre.
  • The action genre contains the highest total revenue out of the other genres.

NOTE: There are numerous variables that go into film making to determine success of a film. Because this data set only includes a subset of movies, the results could be biased. Also, other important variables were not included but could be important to analysis, such as, writer, actor, crew, marketing, etc.

Packages Required

  • dplyr: for data manipulation
  • tidyr: for data cleaning/handling
  • tidyverse: for data manipulation
  • lubridate: for date handling
  • caret: for machine learning
  • relaimpo: To perform relative weight analysis of linear models
  • lmtest: To perform diagnostic checking of linear models
  • fpc: For plotting cluster analysis
  • cluster: For plotting the cluster analysis for Kmeans clusters
  • plotly: For plotting the 3D graphical representation of the cluster analysis
  • splines: In order to perform the linear spline.
  • neuralnet: For plotting neural networks
  • mgcv: To plot the generalized additive model
  • rpart: To assist with plotting decision trees
  • rpart.plot: To assist with plotting decision trees
  • pdftools: To display PDF images into R Markdown
  • DT: To display datatables in R Markdown
  • knitr: To display datatables in R Markdown

Data Cleaning Steps

Data cleaning was performed mostly with Tableau Prep, along with minor manipulation of the csv files.

Below is a list of the data-cleaning steps taken in order to perform an in-depth data analysis:

  • Used ChatGPT to reference the Movies Metadata dataset to provide python code that would reference an online API and pull the director based on the IMDb ID provided in the dataset and create a column of data if it did not already exist.
  • Used an API from https://www.omdbapi.com/ in order to reference all IMDb ID’s to pull the director of each film into the data set.
  • Ran the API within the python code, and exported the new dataset with the new director column added.
  • Created version 2 of the movies metadata dataset file containing the directors.
  • Converted version 2 into an xlsx sheet rather than a csv format in order to import into Tableau Prep Builder.
  • Manually changed the “belongs_to_collection” column to where values that populated said “TRUE” and values that were blank said “FALSE”
  • Deleted 3 rows of data that were incorrect or incomplete and analysis couldn’t be done on them.
  • Formatted Budget and Revenue columns into USD
  • Saved updated file as V3
  • Began further cleaning steps in Tableau Prep Builder. First cleaning step was to remove the entire column of “Adult” as there were only 9 values in the dataset, but no budget provided and no revenue provided. Therefore, were removed from the analysis.
  • Split the “genres” column to pull in the first-level genre that was listed (some films had multiple genres, but the first listed one was the primary).
  • Renamed the split column as “genre”
  • Removed the original “genres” column
  • Removed the “Homepage” column as it was not necessary for the analysis
  • Removed the “Original Title” column as it was not necessary for the analysis
  • Removed the “Overview” column as it was not necessary for the analysis
  • Removed the “poster path” column as it was not necessary for the analysis
  • Removed the “production studio” column as it was not necessary for the analysis
  • Removed the “production country” column as it was not necessary for the analysis
  • Renamed the “runtime” column into “runtime(min)”
  • Removed the “spoken languages” column as it was not necessary for the analysis
  • Added a calculated “Revenue to Budget Ratio” column. This is intended to quickly measure how successful a movie was based on its revenue and listed budget. The higher the number, the more NET profit the movie brought in relative to its budget.

The newly added director variable was a main concern. From a predictive modeling perspective, there are a lot of unique values when it comes to predicting what or who is most successful at generating a higher revenue.

Data Understanding Table

Movies <- read.csv("E:/Spring 2024 Classes/Analytics Capstone/Capstone Project/The Movies Dataset/movies_metadataV4.csv")

Movies <- na.omit(Movies) # Omitting all "NA" values from the data set


Movies <- Movies %>%
  filter(Budget > 0 & Revenue > 0) # Filter out all rows that have a $0 budget and/or revenue


Variable.type <- lapply(Movies,class)
Variable.desc <- c("Specifies if the movie belongs in a collection",
"Name of movie director","Primary listed genre of movie",
"Unique identifier given for movie","Unique identifier of movie from IMdB",
"Original language film was shot in","Release date of the film",
"Release status of film","Tagline of the film",
"Tital of the film","Indicates if there is a provided video on the IMdB website",
"Budget of the film not including marketing costs","Popularity of the film based on top 100 status on IMdB",
"Revenue generated from the film","Calculated field to determine how much revenue a film generated relative to its budget",
"Total runtime of the film in minutes",
"Average vote on a 1 to 10 scale for the film",
"Number of users who gave a review")
Variable.name1 <- colnames(Movies)
data.desc <- as_data_frame(cbind(Variable.name1,Variable.type,Variable.desc))
colnames(data.desc) <- c("Variable Name","Data Type","Variable Description")
kable(data.desc)
Variable Name Data Type Variable Description
Belongs.To.Collection logical Specifies if the movie belongs in a collection
Director character Name of movie director
Genre character Primary listed genre of movie
Id integer Unique identifier given for movie
Imdb.Id character Unique identifier of movie from IMdB
Original.Language character Original language film was shot in
Release.Date character Release date of the film
Status character Release status of film
Tagline logical Tagline of the film
Title character Tital of the film
Video logical Indicates if there is a provided video on the IMdB website
Budget integer Budget of the film not including marketing costs
Popularity numeric Popularity of the film based on top 100 status on IMdB
Revenue numeric Revenue generated from the film
Revenue.to.Budget.Ratio numeric Calculated field to determine how much revenue a film generated relative to its budget
Runtime..Min. integer Total runtime of the film in minutes
Vote.Average numeric Average vote on a 1 to 10 scale for the film
Vote.Count integer Number of users who gave a review

Exploratory Data Visualization

All visualization was performed using Tableau.

## Converting page 1 to Average Revenue Per Collection Status_1.png... done!
Average Revenue Per Collection Status

Average Revenue Per Collection Status

## Converting page 1 to Average Revenue Per Collection Status_1.png... done!

This graph displays the average revenue for all movies based on whether or not they belong into a collection. The visual suggests that movies that belong in a collection, on average, make more revenue than movies that do not belong in a collection. It is important to note that the data is only filtered based on English being the original language the film was created in. This was due to many foreigh films having no listed revenue and thus skewed the averages.

## Converting page 1 to Average Revenue Per Original Language_1.png... done!
Average Revenue Per Original Language

Average Revenue Per Original Language

## Converting page 1 to Average Revenue Per Original Language_1.png... done!

Average of Revenue for each Original Language. In this graph, If the movie was originally produced within the English language, then it had a higher average revenue. This makes sense as Hollywood is the movie capital of the world and the sheer volume of movies output each year compared to the rest of the world would lead to more opportunities for higher revenue on average.

## Converting page 1 to Top Directors by Revenue_1.png... done!
Top Directors by Revenue

Top Directors by Revenue

## Converting page 1 to Top Directors by Revenue_1.png... done!

Keeping with the theme of Hollywood, the original language was purposely filtered to English. Also, the average revenue of movies typically is just over $200 million according to gitnux.org. As such, the revenue was filtered to be at least $200 million of revenue in order to narrow down the list of top directors based on revenue.

## Converting page 1 to Top Genres by Revenue_1.png... done!
Top Genres by Revenue

Top Genres by Revenue

## Converting page 1 to Top Genres by Revenue_1.png... done!

Sum of Revenue broken down by Genre. The data is filtered on Original Language, which keeps en. The view is filtered on sum of Revenue, which includes values greater than or equal to 0. It appears that Action, Adventure, Comedy, and Drama are all heavy hitters when it comes to generating revenue.

## Converting page 1 to Average Revenue Over Time_1.png... done!
Average Revenue Over Time

Average Revenue Over Time

## Converting page 1 to Average Revenue Over Time_1.png... done!
## Converting page 1 to Average Revenue Over Time by Genre_1.png... done!
Average Revenue Over Time by Genre

Average Revenue Over Time by Genre

## Converting page 1 to Average Revenue Over Time by Genre_1.png... done!

The trend of average of Revenue for Release Date Year. Color shows details about Genre. The view is filtered on Genre, which keeps Action, Adventure, Comedy and Drama.

Models and Analysis

Importing data into R

Movies <- read.csv("E:/Spring 2024 Classes/Analytics Capstone/Capstone Project/The Movies Dataset/movies_metadataV4.csv")

str(Movies)
## 'data.frame':    45460 obs. of  18 variables:
##  $ Belongs.To.Collection  : logi  TRUE FALSE TRUE FALSE TRUE FALSE ...
##  $ Director               : chr  "John Lasseter" "Joe Johnston" "Howard Deutch" "Forest Whitaker" ...
##  $ Genre                  : chr  "Animation" "Adventure" "Romance" "Comedy" ...
##  $ Id                     : int  862 8844 15602 31357 11862 949 11860 45325 9091 710 ...
##  $ Imdb.Id                : chr  "tt0114709" "tt0113497" "tt0113228" "tt0114885" ...
##  $ Original.Language      : chr  "en" "en" "en" "en" ...
##  $ Release.Date           : chr  "10/30/1995" "12/15/1995" "12/22/1995" "12/22/1995" ...
##  $ Status                 : chr  "Released" "Released" "Released" "Released" ...
##  $ Tagline                : logi  FALSE TRUE TRUE TRUE TRUE TRUE ...
##  $ Title                  : chr  "Toy Story" "Jumanji" "Grumpier Old Men" "Waiting to Exhale" ...
##  $ Video                  : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ Budget                 : int  30000000 65000000 NA 16000000 NA 60000000 58000000 NA 35000000 58000000 ...
##  $ Popularity             : num  21.95 17.02 11.71 3.86 8.39 ...
##  $ Revenue                : num  3.74e+08 2.63e+08 NA 8.15e+07 7.66e+07 ...
##  $ Revenue.to.Budget.Ratio: num  12.45 4.04 NA 5.09 NA ...
##  $ Runtime..Min.          : int  81 104 101 127 106 170 127 97 106 130 ...
##  $ Vote.Average           : num  7.7 6.9 6.5 6.1 5.7 7.7 6.2 5.4 5.5 6.6 ...
##  $ Vote.Count             : int  5415 2413 92 34 173 1886 141 45 174 1194 ...
Movies <- na.omit(Movies) # Omitting all "NA" values from the data set

Movies$Budget <- as.numeric(gsub("[^0-9]", "", Movies$Budget)) # Declaring Budget to be a numeric value
Movies$Revenue <- as.numeric(gsub("[^0-9]", "", Movies$Revenue)) # Declaring Revenue to be a numeric value

Movies$Release.Date <- mdy(Movies$Release.Date) # Changing the date format of Release.Date
Movies$Year <- year(Movies$Release.Date) # Changing the date format of Year

Movies <- Movies %>%
  filter(Budget > 0 & Revenue > 0) # Filter out all rows that have a $0 budget and/or reveneu

Movies$Genre <- as.factor(Movies$Genre) # Setting the Genre as a factor for ease if data comparisson

str(Movies) # Rechecking values and formats after making changes
## 'data.frame':    5380 obs. of  19 variables:
##  $ Belongs.To.Collection  : logi  TRUE FALSE FALSE FALSE FALSE TRUE ...
##  $ Director               : chr  "John Lasseter" "Joe Johnston" "Forest Whitaker" "Michael Mann" ...
##  $ Genre                  : Factor w/ 21 levels "","Action","Adventure",..: 4 3 5 2 2 3 5 12 2 8 ...
##  $ Id                     : int  862 8844 31357 949 9091 710 9087 10858 1408 524 ...
##  $ Imdb.Id                : chr  "tt0114709" "tt0113497" "tt0114885" "tt0113277" ...
##  $ Original.Language      : chr  "en" "en" "en" "en" ...
##  $ Release.Date           : Date, format: "1995-10-30" "1995-12-15" ...
##  $ Status                 : chr  "Released" "Released" "Released" "Released" ...
##  $ Tagline                : logi  FALSE TRUE TRUE TRUE TRUE TRUE ...
##  $ Title                  : chr  "Toy Story" "Jumanji" "Waiting to Exhale" "Heat" ...
##  $ Video                  : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ Budget                 : num  3.0e+07 6.5e+07 1.6e+07 6.0e+07 3.5e+07 5.8e+07 6.2e+07 4.4e+07 9.8e+07 5.2e+07 ...
##  $ Popularity             : num  21.95 17.02 3.86 17.92 5.23 ...
##  $ Revenue                : num  3.74e+08 2.63e+08 8.15e+07 1.87e+08 6.44e+07 ...
##  $ Revenue.to.Budget.Ratio: num  12.45 4.04 5.09 3.12 1.84 ...
##  $ Runtime..Min.          : int  81 104 127 170 106 130 106 192 119 178 ...
##  $ Vote.Average           : num  7.7 6.9 6.1 7.7 5.5 6.6 6.5 7.1 5.7 7.8 ...
##  $ Vote.Count             : int  5415 2413 34 1886 174 1194 199 72 137 1343 ...
##  $ Year                   : num  1995 1995 1995 1995 1995 ...
##  - attr(*, "na.action")= 'omit' Named int [1:40080] 3 5 7 8 12 13 22 24 26 28 ...
##   ..- attr(*, "names")= chr [1:40080] "3" "5" "7" "8" ...
#############################
#  Linear Regression Model  #
#############################

movie_reg <- lm(Revenue ~ Genre + Budget + Tagline + Original.Language + Year + Video + Popularity + Runtime..Min. + Vote.Average + Director, data = Movies) # The first regression capture all variables that could influence Revenue 

# Capture the summary output as a character vector
summary_output <- capture.output(summary(movie_reg))

# Display only the first 50 lines of the summary
cat(head(summary_output, 50), sep = "\n")
## 
## Call:
## lm(formula = Revenue ~ Genre + Budget + Tagline + Original.Language + 
##     Year + Video + Popularity + Runtime..Min. + Vote.Average + 
##     Director, data = Movies)
## 
## Residuals:
##        Min         1Q     Median         3Q        Max 
## -770432321  -17638023          0   13973638 1298041924 
## 
## Coefficients: (22 not defined because of singularities)
##                                                                                                                                                                                                                                                       Estimate
## (Intercept)                                                                                                                                                                                                                                          1.499e+09
## GenreAction                                                                                                                                                                                                                                         -1.082e+08
## GenreAdventure                                                                                                                                                                                                                                      -9.308e+07
## GenreAnimation                                                                                                                                                                                                                                      -1.028e+08
## GenreComedy                                                                                                                                                                                                                                         -9.202e+07
## GenreCrime                                                                                                                                                                                                                                          -1.113e+08
## GenreDocumentary                                                                                                                                                                                                                                    -1.785e+08
## GenreDrama                                                                                                                                                                                                                                          -1.169e+08
## GenreFamily                                                                                                                                                                                                                                         -9.167e+07
## GenreFantasy                                                                                                                                                                                                                                        -1.043e+08
## GenreForeign                                                                                                                                                                                                                                        -3.972e+07
## GenreHistory                                                                                                                                                                                                                                        -1.205e+08
## GenreHorror                                                                                                                                                                                                                                         -1.097e+08
## GenreMusic                                                                                                                                                                                                                                          -1.386e+08
## GenreMystery                                                                                                                                                                                                                                        -1.232e+08
## GenreRomance                                                                                                                                                                                                                                        -9.282e+07
## GenreScience Fiction                                                                                                                                                                                                                                -1.146e+08
## GenreThriller                                                                                                                                                                                                                                       -1.058e+08
## GenreTV Movie                                                                                                                                                                                                                                       -1.352e+08
## GenreWar                                                                                                                                                                                                                                            -1.473e+08
## GenreWestern                                                                                                                                                                                                                                        -1.488e+08
## Budget                                                                                                                                                                                                                                               2.452e+00
## TaglineTRUE                                                                                                                                                                                                                                         -1.651e+06
## Original.Languagebm                                                                                                                                                                                                                                 -4.444e+07
## Original.Languageca                                                                                                                                                                                                                                 -7.218e+07
## Original.Languagecn                                                                                                                                                                                                                                 -2.875e+08
## Original.Languageda                                                                                                                                                                                                                                 -1.082e+07
## Original.Languagede                                                                                                                                                                                                                                 -9.534e+07
## Original.Languageel                                                                                                                                                                                                                                 -5.952e+07
## Original.Languageen                                                                                                                                                                                                                                 -4.984e+07
## Original.Languagees                                                                                                                                                                                                                                 -5.015e+07
## Original.Languagefa                                                                                                                                                                                                                                 -1.125e+08
## Original.Languagefi                                                                                                                                                                                                                                 -3.935e+07
## Original.Languagefr                                                                                                                                                                                                                                 -4.078e+07
## Original.Languagehe                                                                                                                                                                                                                                 -5.144e+07
## Original.Languagehi                                                                                                                                                                                                                                 -7.893e+07
## Original.Languagehu                                                                                                                                                                                                                                 -4.529e+07
## Original.Languageid                                                                                                                                                                                                                                 -3.257e+07

There are several variables that have certain specific values that are statistically significant, but also have a lot of specific values that aren’t. For example, each director has their own P-Value to determine

statistical significance. For the directors that are statistically significant, it would be difficult to determine if this is because they are influencing Revenue more than others, or if they are simply an outlier in the data (i.e. a single director directed more movies in the set than others, etc.).

Therefore, values that are NOT statistically significant will be removed for the next iteration of regression along with complex variables such as director. However, given the data set, the Adjusted R-squared value is 0.53, which is very optimistic given that the data set has a small subset of variables compared to how many could be applied in the film industry.

movie_reg2 <- lm(Revenue ~ Genre + Budget + Tagline + Year + Popularity + Runtime..Min. + Vote.Average, data = Movies)
summary(movie_reg2)
## 
## Call:
## lm(formula = Revenue ~ Genre + Budget + Tagline + Year + Popularity + 
##     Runtime..Min. + Vote.Average, data = Movies)
## 
## Residuals:
##        Min         1Q     Median         3Q        Max 
## -877326093  -39097582   -6264081   24755196 1683709340 
## 
## Coefficients:
##                        Estimate Std. Error t value Pr(>|t|)    
## (Intercept)           1.223e+08  1.987e+08   0.615  0.53831    
## GenreAction          -6.512e+07  3.067e+07  -2.123  0.03377 *  
## GenreAdventure       -5.388e+07  3.099e+07  -1.739  0.08217 .  
## GenreAnimation       -9.445e+06  3.189e+07  -0.296  0.76711    
## GenreComedy          -4.817e+07  3.064e+07  -1.572  0.11600    
## GenreCrime           -7.753e+07  3.118e+07  -2.487  0.01292 *  
## GenreDocumentary     -5.447e+07  3.410e+07  -1.597  0.11028    
## GenreDrama           -7.102e+07  3.063e+07  -2.318  0.02047 *  
## GenreFamily          -4.372e+07  3.375e+07  -1.295  0.19522    
## GenreFantasy         -6.365e+07  3.179e+07  -2.002  0.04534 *  
## GenreForeign         -2.912e+07  6.064e+07  -0.480  0.63114    
## GenreHistory         -6.879e+07  3.624e+07  -1.898  0.05770 .  
## GenreHorror          -4.070e+07  3.104e+07  -1.311  0.18980    
## GenreMusic           -7.403e+07  3.541e+07  -2.090  0.03663 *  
## GenreMystery         -7.354e+07  3.308e+07  -2.223  0.02623 *  
## GenreRomance         -5.061e+07  3.193e+07  -1.585  0.11300    
## GenreScience Fiction -6.314e+07  3.222e+07  -1.960  0.05010 .  
## GenreThriller        -6.423e+07  3.137e+07  -2.047  0.04069 *  
## GenreTV Movie        -5.636e+07  1.093e+08  -0.516  0.60614    
## GenreWar             -1.009e+08  3.493e+07  -2.890  0.00387 ** 
## GenreWestern         -9.793e+07  3.593e+07  -2.725  0.00644 ** 
## Budget                2.640e+00  4.395e-02  60.072  < 2e-16 ***
## TaglineTRUE          -1.077e+06  4.305e+06  -0.250  0.80250    
## Year                 -1.212e+05  9.735e+04  -1.245  0.21317    
## Popularity            2.591e+06  1.123e+05  23.076  < 2e-16 ***
## Runtime..Min.         1.035e+05  7.478e+04   1.384  0.16647    
## Vote.Average          2.356e+07  1.731e+06  13.613  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.05e+08 on 5353 degrees of freedom
## Multiple R-squared:  0.5925, Adjusted R-squared:  0.5905 
## F-statistic: 299.4 on 26 and 5353 DF,  p-value: < 2.2e-16

This iteration of regression shows an improved adjusted R-squared value of 0.5905 which is promising.

Tagline, year, and runtime variables also bare no statistical significance and will be removed from the next iteration of regression.

movie_reg3 <- lm(Revenue ~ Budget + Popularity + Vote.Average, data = Movies)
summary(movie_reg3)
## 
## Call:
## lm(formula = Revenue ~ Budget + Popularity + Vote.Average, data = Movies)
## 
## Residuals:
##        Min         1Q     Median         3Q        Max 
## -872429663  -39885488   -7208884   24327802 1678383352 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -1.632e+08  9.993e+06  -16.33   <2e-16 ***
## Budget        2.665e+00  3.777e-02   70.56   <2e-16 ***
## Popularity    2.591e+06  1.112e+05   23.29   <2e-16 ***
## Vote.Average  2.245e+07  1.581e+06   14.20   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 105700000 on 5376 degrees of freedom
## Multiple R-squared:  0.5853, Adjusted R-squared:  0.585 
## F-statistic:  2529 on 3 and 5376 DF,  p-value: < 2.2e-16
plot(Movies$Revenue, Movies$Budget, xlab = "Revenue", ylab = "Budget", main = "Revenue vs. Budget")
abline(movie_reg, col = "blue", lwd = 1)
abline(movie_reg2, col = "red", lwd = 1)
abline(movie_reg3, col = "green", lwd = 1)

This third iteration of regression returns a slightly lower R-squared value of 0.585. All variables in model 3 are statistically significant. However, model 2 provides a slightly higher adjusted R-squared value. The Revenue vs. Budget plot indicates some linearity between Revenue and Budget, or at least multiple linear relationships could be existing at once. Interestingly, the 3rd regression plotted against Revenue vs. Budget appears to more closely follow where the data is trending. As such, only the regression plots of model 3 will be discussed.

plot(movie_reg3, pch = 16, col = "blue")

Residuals vs. Fitting plot: This plot helps determine how close to linearity the data is following and corresponds with the regression plot above.

There do appear to be 3 statistical outliers as highlighted in the residuals vs. fitted plot. Also, it’s worth noting that this plot suggests that the relationship is not fully linear

due to groups of data appearing to form a specific pattern as opposed to being evenly distributed along the residual = 0 line.

Q-Q Residuals: This plot simply indicates that the data is not normally distributed data. This is indicated by the head and tail of the graph curving toward the extreme values. If this data was normally distributed, then the graph would appear to form more of a straight line.

Scale-Location Plot: The scale location plot that is severly skewed. Normally, the plot would appear to be as horizontal as possible. However, this graph indicates that there is not equal variance.

Residuals vs. Leverage plot: This plot indicates that there are 2 observed values that could potentially change the coefficients of model 3 significantly.

#############################
# Relative Weight Analysis  #
#############################

rel_weights <- calc.relimp(movie_reg3, type = c("lmg", "last", "first", "pratt"))

print(rel_weights)
## Response variable: Revenue 
## Total response variance: 2.690333e+16 
## Analysis based on 5380 observations 
## 
## 3 Regressors: 
## Budget Popularity Vote.Average 
## Proportion of variance explained by model: 58.53%
## Metrics are not normalized (rela=FALSE). 
## 
## Relative importance metrics: 
## 
##                     lmg       last      first      pratt
## Budget       0.44949282 0.38407654 0.51703979 0.46925590
## Popularity   0.11658558 0.04184383 0.19345802 0.09600551
## Vote.Average 0.01917346 0.01556565 0.02491196 0.01999046
## 
## Average coefficients for different model sizes: 
## 
##                        1X          2Xs          3Xs
## Budget       2.936421e+00 2.786781e+00 2.665042e+00
## Popularity   5.220563e+06 3.956156e+06 2.590757e+06
## Vote.Average 2.797910e+07 2.228316e+07 2.245167e+07

Budget: Has the highest lmg (0.4495), indicating that it is the most important predictor when considering the average contribution across all possible orders of the predictors. It also has the highest pratt value (0.4693), reinforcing its position as the most influential variable in the model.

Popularity: lmg of 0.1166, which is lower than Budget, suggesting it is less important but still has a significant role in explaining Revenue. last and first metrics indicate that Popularity contributes more when it is the first variable in the model than when it is the last.

Vote.Average: Shows the lowest lmg (0.0192), suggesting it has the least influence on explaining the variance in Revenue. Consistent with last and first metrics, Vote.Average seems to play a smaller role compared to Budget and Popularity.

Budget is the most critical factor influencing Revenue, and its relative importance is significant regardless of the model’s configuration.

Popularity is also a meaningful predictor but not as strong as Budget. Its relative importance decreases as other predictors are introduced into the model.

Vote.Average has the least relative importance, suggesting that while it may affect Revenue, it does so to a lesser extent than Budget or Popularity.

This analysis suggests that, to maximize Revenue, a focus on increasing Budget (possibly indicating larger productions or more substantial investments in marketing) and Popularity (which may relate to promotional activities and broader audience appeal) should be prioritized over Vote.Average, which might relate to critical reception or audience ratings.

# Because the data may not show a linear relationship, a regression spline is considered. The spline provides a method to consolidate multiple points of data into "batches" 
# the resulting spline regression attempts to smoothly and accurately plot the relationship. 

#############################
#       Linear Spline       #
#############################

movie_spline <- lm(Movies$Budget~bs(Movies$Revenue, df = 4,), data = Movies)
summary(movie_spline)
## 
## Call:
## lm(formula = Movies$Budget ~ bs(Movies$Revenue, df = 4, ), data = Movies)
## 
## Residuals:
##        Min         1Q     Median         3Q        Max 
## -141965729  -11286458   -5031371    7309623  291477130 
## 
## Coefficients:
##                                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                     8430251     775710  10.868  < 2e-16 ***
## bs(Movies$Revenue, df = 4, )1   8200904    1099564   7.458 1.02e-13 ***
## bs(Movies$Revenue, df = 4, )2 239753236    6111948  39.227  < 2e-16 ***
## bs(Movies$Revenue, df = 4, )3 180756002   19600351   9.222  < 2e-16 ***
## bs(Movies$Revenue, df = 4, )4 240187041   25180714   9.539  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 26780000 on 5375 degrees of freedom
## Multiple R-squared:  0.5558, Adjusted R-squared:  0.5555 
## F-statistic:  1681 on 4 and 5375 DF,  p-value: < 2.2e-16
# The adjusted R-squared value is very comparable to the linear regression model at 0.5555, but is slightly lower than the selected linear regression model. 

movie_conf <- predict(movie_spline, interval = "confidence", level = 0.95)

# Capture the confidence output as a character vector
confidience_output <- capture.output(movie_conf)

# Display only the first 10 lines of the output
cat(head(confidience_output, 10), sep = "\n")
##            fit       lwr       upr
## 1     93792807  91730978  95854635
## 2     73232970  71552483  74913458
## 3     34279271  33363033  35195508
## 4     57871365  56552058  59190672
## 5     30246663  29310611  31182714
## 6     90008567  88007423  92009710
## 7     40385672  39429370  41341975
## 8     17319542  16235594  18403489
## 9     15653241  14688643  16617839
movie_conf <- as.data.frame(movie_conf)

plot(Movies$Revenue, Movies$Budget, xlab = "Revenue", main = "Regression Spline", ylab = "Budget", cex = 1.5)
lines(Movies$Revenue, movie_spline$fitted.values, col = "blue", lwd = 1)
lines(Movies$Revenue, movie_conf$lwr, col = "red", lty = 2)
lines(Movies$Revenue, movie_conf$upr, col = "red", lty = 2)

The plotted values and confidence limits appear to flow along with the data much better than the linear regression model 3. However, this graph seems to also display multiple relationships ocurring with multiple confidence limits to consider for each.

With revenue and budget being the highest numerical values to consider, normalization of the data will be considered next. Normalizing the data seems to be the most appropriate approach due to the vast range of numerical values and variables.

str(Movies) # Identifying non-numeric variables to exclude/convert
## 'data.frame':    5380 obs. of  19 variables:
##  $ Belongs.To.Collection  : logi  TRUE FALSE FALSE FALSE FALSE TRUE ...
##  $ Director               : chr  "John Lasseter" "Joe Johnston" "Forest Whitaker" "Michael Mann" ...
##  $ Genre                  : Factor w/ 21 levels "","Action","Adventure",..: 4 3 5 2 2 3 5 12 2 8 ...
##  $ Id                     : int  862 8844 31357 949 9091 710 9087 10858 1408 524 ...
##  $ Imdb.Id                : chr  "tt0114709" "tt0113497" "tt0114885" "tt0113277" ...
##  $ Original.Language      : chr  "en" "en" "en" "en" ...
##  $ Release.Date           : Date, format: "1995-10-30" "1995-12-15" ...
##  $ Status                 : chr  "Released" "Released" "Released" "Released" ...
##  $ Tagline                : logi  FALSE TRUE TRUE TRUE TRUE TRUE ...
##  $ Title                  : chr  "Toy Story" "Jumanji" "Waiting to Exhale" "Heat" ...
##  $ Video                  : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ Budget                 : num  3.0e+07 6.5e+07 1.6e+07 6.0e+07 3.5e+07 5.8e+07 6.2e+07 4.4e+07 9.8e+07 5.2e+07 ...
##  $ Popularity             : num  21.95 17.02 3.86 17.92 5.23 ...
##  $ Revenue                : num  3.74e+08 2.63e+08 8.15e+07 1.87e+08 6.44e+07 ...
##  $ Revenue.to.Budget.Ratio: num  12.45 4.04 5.09 3.12 1.84 ...
##  $ Runtime..Min.          : int  81 104 127 170 106 130 106 192 119 178 ...
##  $ Vote.Average           : num  7.7 6.9 6.1 7.7 5.5 6.6 6.5 7.1 5.7 7.8 ...
##  $ Vote.Count             : int  5415 2413 34 1886 174 1194 199 72 137 1343 ...
##  $ Year                   : num  1995 1995 1995 1995 1995 ...
##  - attr(*, "na.action")= 'omit' Named int [1:40080] 3 5 7 8 12 13 22 24 26 28 ...
##   ..- attr(*, "names")= chr [1:40080] "3" "5" "7" "8" ...
# Removing all non-numeric variables

Movies2 <- Movies[,-c(1:11,16,18,19)]

str(Movies2)
## 'data.frame':    5380 obs. of  5 variables:
##  $ Budget                 : num  3.0e+07 6.5e+07 1.6e+07 6.0e+07 3.5e+07 5.8e+07 6.2e+07 4.4e+07 9.8e+07 5.2e+07 ...
##  $ Popularity             : num  21.95 17.02 3.86 17.92 5.23 ...
##  $ Revenue                : num  3.74e+08 2.63e+08 8.15e+07 1.87e+08 6.44e+07 ...
##  $ Revenue.to.Budget.Ratio: num  12.45 4.04 5.09 3.12 1.84 ...
##  $ Vote.Average           : num  7.7 6.9 6.1 7.7 5.5 6.6 6.5 7.1 5.7 7.8 ...
maxs <- apply(Movies2, 2, max)
mins <- apply(Movies2, 2, min)

scaled <- as.data.frame(scale(Movies2, center = mins, scale = maxs - mins))
summary(scaled)
##      Budget          Popularity          Revenue        
##  Min.   :0.00000   Min.   :0.000000   Min.   :0.000000  
##  1st Qu.:0.01323   1st Qu.:0.009947   1st Qu.:0.001390  
##  Median :0.04474   Median :0.015323   Median :0.009131  
##  Mean   :0.08184   Mean   :0.017856   Mean   :0.030814  
##  3rd Qu.:0.10526   3rd Qu.:0.021408   3rd Qu.:0.033681  
##  Max.   :1.00000   Max.   :1.000000   Max.   :1.000000  
##  Revenue.to.Budget.Ratio  Vote.Average   
##  Min.   :0.0000000       Min.   :0.0000  
##  1st Qu.:0.0000001       1st Qu.:0.6264  
##  Median :0.0000002       Median :0.6923  
##  Mean   :0.0004491       Mean   :0.6894  
##  3rd Qu.:0.0000003       3rd Qu.:0.7582  
##  Max.   :1.0000000       Max.   :1.0000
str(Movies2)
## 'data.frame':    5380 obs. of  5 variables:
##  $ Budget                 : num  3.0e+07 6.5e+07 1.6e+07 6.0e+07 3.5e+07 5.8e+07 6.2e+07 4.4e+07 9.8e+07 5.2e+07 ...
##  $ Popularity             : num  21.95 17.02 3.86 17.92 5.23 ...
##  $ Revenue                : num  3.74e+08 2.63e+08 8.15e+07 1.87e+08 6.44e+07 ...
##  $ Revenue.to.Budget.Ratio: num  12.45 4.04 5.09 3.12 1.84 ...
##  $ Vote.Average           : num  7.7 6.9 6.1 7.7 5.5 6.6 6.5 7.1 5.7 7.8 ...
Index2 <- sample(nrow(Movies2), nrow(Movies2)*0.85)

Movies2_Train <- scaled[Index2,]
Movies2_Test <- scaled[-Index2,]

# The neural network is plotted primarily to assist in calculating the Mean Squared Error from the spline

Movie_NN <- neuralnet(Movies2_Train$Revenue~., data = Movies2_Train, hidden = c(4,3,4), linear.output = FALSE)

Movie_NN$act.fct
## function (x) 
## {
##     1/(1 + exp(-x))
## }
## <bytecode: 0x0000023a0e28c678>
## <environment: 0x0000023a0e28d018>
## attr(,"type")
## [1] "logistic"
plot(Movie_NN)

str(Movies2_Test)
## 'data.frame':    807 obs. of  5 variables:
##  $ Budget                 : num  0.1579 0.1526 0.0796 0.0289 0.0526 ...
##  $ Popularity             : num  0.0327 0.0268 0.0231 0.0126 0.0191 ...
##  $ Revenue                : num  0.06723 0.12633 0.04129 0.01412 0.00763 ...
##  $ Revenue.to.Budget.Ratio: num  2.52e-07 4.90e-07 3.07e-07 2.89e-07 8.58e-08 ...
##  $ Vote.Average           : num  0.846 0.725 0.703 0.802 0.736 ...
str(Movies2_Train)
## 'data.frame':    4573 obs. of  5 variables:
##  $ Budget                 : num  0.02395 0.07105 0.01579 0.00263 0.01371 ...
##  $ Popularity             : num  0.00801 0.00533 0.00836 0.00328 0.01253 ...
##  $ Revenue                : num  1.35e-02 2.73e-06 2.94e-03 6.26e-04 2.12e-03 ...
##  $ Revenue.to.Budget.Ratio: num  3.34e-07 2.27e-07 1.10e-07 1.41e-07 9.14e-08 ...
##  $ Vote.Average           : num  0.791 0.648 0.703 0.692 0.747 ...
Movies_pred <- compute(Movie_NN, Movies2_Test)

Movies_pred_org <- Movies_pred$net.result*(max(Movies2$Budget) - min(Movies2$Budget)) + min(Movies2$Budget) # Prediction for the revenue.

# Capture the prediction output as a character vector
prediction_output <- capture.output(Movies_pred_org)

# Display only the first 10 lines of the output
cat(head(prediction_output, 10), sep = "\n")
##             [,1]
## 4     34621720.0
## 6     24098152.0
## 15    12458408.3
## 22     4832128.6
## 24     8222728.5
## 33     1053044.6
## 43     8057642.4
## 46     4798482.7
## 48     7032647.9
test_r <- (Movies2_Test$Budget)*(max(Movies2$Budget) - min(Movies2$Budget)) + min(Movies2$Budget)

MSPE_nn <- sum((test_r - Movies_pred_org)^2)/nrow(Movies2_Test)

MSPE_nn
## [1] 1.147328e+15

Extremely large error. Regression spline does not appear to be an appropriate way to predict revenue.

The plotted GAM charts show the smoothing splines for Budget and the Vote Average as declared in the game model.

The GAM model appears to be promising. Using the same setup as Regression 3, the adjusted R-squared value increased to 0.605 with 60.5% of the deviance explained. It’s also important to note that the all variables are considered to not have a linear relationship with the target variable.

#############################
#       Decision Tree       #
#############################

# A decision tree helps indicate which variables are the most influential to the target variable


## Printing and plotting the tree

Index1 <- sample(nrow(Movies), nrow(Movies)*0.85)

Movies_Train <- Movies[Index1,]
Movies_Test <- Movies[-Index1,]

movie_rpart <- rpart(formula = Revenue ~ Budget + Popularity + Vote.Average, data = Movies_Train) # In the output here, deviance is the mean squared error. 
movie_rpart
## n= 4573 
## 
## node), split, n, deviance, yval
##       * denotes terminal node
## 
##  1) root 4573 1.207406e+20   85082030  
##    2) Budget< 9.1e+07 4231 3.770081e+19   56993900  
##      4) Budget< 3.675e+07 3340 1.337647e+19   35828830  
##        8) Popularity< 8.843162 2130 2.560229e+18   20180450 *
##        9) Popularity>=8.843162 1210 9.376513e+18   63375160 *
##      5) Budget>=3.675e+07 891 1.721955e+19  136333200  
##       10) Popularity< 15.67376 782 8.740058e+18  115478000 *
##       11) Popularity>=15.67376 109 5.699223e+18  285955000 *
##    3) Budget>=9.1e+07 342 3.840604e+19  432569900  
##      6) Popularity< 23.61124 274 1.498188e+19  351999100  
##       12) Budget< 1.775e+08 241 9.652110e+18  317901800 *
##       13) Budget>=1.775e+08 33 3.003326e+18  601012600 *
##      7) Popularity>=23.61124 68 1.447827e+19  757223000  
##       14) Budget< 1.875e+08 47 5.114232e+18  622953400  
##         28) Vote.Average< 6.75 16 1.647616e+18  397396100 *
##         29) Vote.Average>=6.75 31 2.232460e+18  739370100 *
##       15) Budget>=1.875e+08 21 6.620296e+18 1057731000  
##         30) Vote.Average< 7.15 14 1.350662e+18  833073100 *
##         31) Vote.Average>=7.15 7 3.149841e+18 1507047000 *
prp(movie_rpart, digits = 6, extra = 1) # extra = 1 allows us to see the number of observations in each node

The tree was plotted using the same variable list as linear regression 3. This maps out how each variable and its values can influence the overall revenue of a film. The number of observations in each node provides interesting information. As in, the majority of data points either had a popularity score of under 9.522 with a budget of less than $36.75 Mil.

Cluster 1 (High Budget, High Popularity): This cluster likely represents blockbuster movies with significant investment and high audience engagement. Strategies for these films may involve heavy marketing campaigns and wide releases.

Cluster 2 (Low Budget, Low Popularity): Represents independent or lower-budget films that might have limited appeal. These might require targeted marketing strategies or niche audience engagement.

Cluster 3 (Moderate across metrics): Films that do not excel in any particular area but perform decently across the board. Strategies here might focus on leveraging moderate popularity to increase visibility or pairing with similar movies to enhance viewer recommendations.

Summary

The exploratory visualization and models uncovered insights about the data that can assist with some decision making for Amazon.

  • Action, Adventure, and Fantasy genres appear to generate higher revenue on average. Generes are often intermixed into Action/Fantasy, or Adventure/Fantasy. There was unfortunately not enough data to determine if mixing genres would be a more profitable solution. However, this presents an opportunity for further analysis.
  • The US produces more films by far, and has the most history with film making. Further analysis should be used to explore how other countries measure up.
  • High budget seems to be a good strategy to produce higher grossing films. However, this should be further studied to have more correlations made. Marketing analysis should be performed to determine if the risk is worth the reward.
  • In the cluster analysis, higher ratings did appear to correlate with higher revenue. Having a winning formula for movies would warranty further analysis on writers, actors, etc. For example, are certain writers associated with higher grossing films than others? Even a film’s composer could make a difference (i.e. John Williams: Star Wars, Indiana Jones, etc.).