Course: Foundations of Data Science Institute: EPFL Extension School Project Title: Final project, Report 4 Author: Elo Ogbokor Learner Name: 𝓜𝓮𝓻𝓶𝓪𝓲𝓭𝓼 𝓞𝓷𝓵𝔂 Date: 12 February 2025
Part completed.
Attempted to find answer, however unfruitful result.
Unattempted.
In this project, you will have to use an API to acquire your data from the web.
The API used in this project is the “The Movie DB”. Unlike the APIs we used in the units, this one will ask you to create an account and use a key in all your queries (i.e., inside the URL). This is much closer to a real-life scenario, as most serious APIs use this kind of authentication system.
First, you will need to create an account. You can use your @extensionschool.ch email for this.
You will probably be asked to verify your account (i.e., click on a link sent to your email and re-enter your username and password).
Once this is done, you will have an account on “The Movie DB”, but that is not enough to use the API. We now need to create an “API application” in the account (i.e., a project).
Creating an “application” is a common API pattern and many API providers (including Google and X) ask you to do such a thing. This is a way for them to see if you will use their data for commercial purposes (and charge you if so).
Go to the settings of your account by clicking on the little initial logo on the top right-hand side and click “Settings”.
In your “Settings” page, click on “API” in the left-hand side menu (➊), then “Create” (➋) and choose “Developer” (➌), since you are an individual and developing a not-for-profit project.
After you accept the “Terms and Conditions”, you will be asked for some information. If you do not want to give out your personal details, please use the Extension School ones (as we checked with “The Movie DB” that this course was fair use):
Type of Use: Education (from the drop-down menu) Application name: your EXTS username (or anything else) First Name: First two letters of your username Last Name: Last two letters of your username Application URL: Since we do not plan to use the data in a web application, you can write “localhost.com” for the URL (it means that this application will only live on your computer). Application Summary: Course project for EPFL EXTS Email Address: This should be filled automatically with the email you provided for your account Phone Number: 0216935041 Address1: EPFL Extension School Address2: EPFL Innovation Park, Building E Zip Code: 1015 City: Lausanne State: Vaud Country: Switzerland If all went well, you should now have an API Key on your “Settings” page. Congratulations, you just created a real account on a real professional API!
my api key: 654e4b35f65127c0678db032bad501cc
Inspired by the example query above, create queries to request the following information:
For starters, I required the Drama id number.
I used link: https://www.themoviedb.org/talk/5daf6eb0ae36680011d7e6ee to display genre ids.
Unveil movie genre ids in Insomnia.
query for highest grossing 2010 dramas:
-> where &primary_release_year=2010 for specifying year &sort_by=revenue.desc to arrange according to highest grossing films &with_genres=18, 18 is Drama genre id
Highest grossing 2010 dramas request. Since it was not specified how many movies to extract, I only extracted the first 20 of page 1.
Creating “high_gross_drama_table”
high_gross_drama_table <- high_gross_2010_drama_req %>%
resp_body_json() %>%
pluck("results") %>%
map(extract, c("original_title")) %>%
map(flatten_df) %>%
bind_rows() %>%
rename("highest_grossing_2010_dramas" = "original_title")
high_gross_drama_table
high_gross_drama_string <- high_gross_drama_table %>%
toString()
The top 20 highest grossing dramas of 2010 are: c(“The Twilight Saga: Eclipse”, “The King’s Speech”, “The Karate Kid”, “Black Swan”, “Shutter Island”, “Sex and the City 2”, “True Grit”, “The Social Network”, “Due Date”, “Eat Pray Love”, “Step Up 3D”, “The Town”, “Wall Street: Money Never Sleeps”, “The Fighter”, “Dear John”, “Hereafter”, “Life As We Know It”, “Love & Other Drugs”, “唐山大地震”, “Green Zone”)
When extracting deeply nested items from a list, the code order matters.
For example:
&&
would produce different results.
Code explanation:
I used api request “https://api.themoviedb.org/3/discover/movie?api_key=654e4b35f65127c0678db032bad501cc&primary_release_year=2010&sort_by=revenue.desc&with_genres=18” to unveil the details of the highest grossing movies of 2010. Next, I converted the content from list form to table form.
Observations:
There is one movie title on the list “original_title”:“唐山大地震” which is not in the English language.
To begin, I attempted using actor names directly, which failed. After I required actor ids. Using https://developer.themoviedb.org/reference/search-person , I was able to extract the actors respective ids.
query, Will Ferrell
https://api.themoviedb.org/3/discover/movie?api_key=654e4b35f65127c0678db032bad501cc&with_cast=23659
query, Liam Neeson
https://api.themoviedb.org/3/discover/movie?api_key=654e4b35f65127c0678db032bad501cc&with_cast=3896
Ferrell
Creating vector to store every page number which displays Ferrell’s movies. Range 1-6 was determined as page 1 is first page and 6 last page is from “total_pages” in api request result.
Ferrell_movies_pages <- c(
1:
6
)
Ferrell_movies_pages
## [1] 1 2 3 4 5 6
Generating API requests for Ferrell’s movies results pages.
Extracting Ferrell’s movies
ferrell_movies <- ferrell_mov_reqs %>%
map(req_perform) %>%
map(resp_body_json) %>%
map(pluck("results")) %>%
#JUST NEED TO UNNEST genre_ids<list>
#use this for now as im out of plans
flatten_df() %>%
#(-genre_ids) %>%
#unnest(genre_ids) %>%
unique() %>%
#ALMOST, JUST NEED TO FIGURE TO EXTRACT ALL MOVIES INTO TABLE
arrange(title)
#map(flatten) %>%
#map(extract, c("original_title"))
ferrell_movies
Neeson
Neeson movie request
Creating vector to store every page number which displays Neeson’s movies. Range 1-10 was determined as page 1 is first page and 10 last page is from “total_pages” in api request result.
Neeson_movies_pages <- c(
1:
10
)
Neeson_movies_pages
## [1] 1 2 3 4 5 6 7 8 9 10
Generating API requests for Neeson’s movies results pages.
Extracting Neeson’s movies
neeson_movies <- liam_neeson_mov_reqs %>%
map(req_perform) %>%
map(resp_body_json) %>%
map(pluck("results")) %>%
#JUST NEED TO UNNEST🪺 genre_ids<list>
flatten_df() %>%
#unnest(genre_ids) %>%
select(-genre_ids) %>%
unique() %>%
arrange(title) %>%
#map(flatten) %>%
#map(extract, c("original_title"))
select("id",
"original_title",
"title",
"overview",
"release_date",
"original_language",
#"genre_ids"
"popularity",
"backdrop_path",
"poster_path",
"video",
"adult",
"vote_average",
"vote_count")
neeson_movies
Joining Ferrell and Neeson’s tables to determine whether they have appeared in identical movie(s).
neeson_and_ferrell_movies <-ferrell_movies %>%
inner_join(neeson_movies, by = c("id",
"original_title",
"title")) %>%
select(id,
title) %>%
arrange(title)
neeson_and_ferrell_movies
The answer is yes, Neeson and Ferrell have starred in the identical movies as viewed in table “neeson_and_ferrell_movies”, namely:
Code explanation:
To begin, I stored all the pages which display the movie results of both actors into their respective variables. Next, I used purr:map to iterate the page numbers and display the api requests. After, I converted the api requests results for Neeson and Ferrell into table form. In the next step, I used an inner_join() to identify whether any movies appear in both tables, which would indicate both starring in identical movies.
Observations:
Neeson and Ferrell have starred in 3 movies together.
query typed into Insomnia:
https://api.themoviedb.org/3/discover/movie?api_key=654e4b35f65127c0678db032bad501cc&with_cast=500&certification_country=US and&certification.lte=G
According to above image “Tom Cruise kids movies query” , the
answer is no, there are no kids movies starring Tom Cruise, since
“total_results” reads 0.
Code explanation:
No code used, as API query was sufficient.
Observations:
As viewed under “Part 1.c, Answer”, Tom Cruise does not star in children’s movies, meaning his films are geared towards a mature audience.
Answer the questions and include the queries and results (tibbles) in the report.
Hints:
When you query for movies of a specific genre, use the ID of the genre. To get the list of official movie genres and their IDs, visit this page. Send the request on the right-hand side by using the “Try It!” button so the response with the IDs will be displayed below.
You need the following parameters to get the kids’ movies: certification_country=US and certification.lte=G.
Write a query to find the ID of the animation movie company “Pixar”. Show both the query and how you extract the ID from the result in your report. Add the ID as inline code in your report.
Hint: In this case, you should check the Search endpoints.
First, I opened link https://developer.themoviedb.org/reference/search-company Next, I entered “Pixar” into the “query string” text-box under “Query Params.”
Pixar id query:
extracting_pixar_id <- pixar_id_req %>%
resp_body_json() %>%
pluck("results") %>%
map(extract, c("id",
"name",
"origin_country")) %>%
map(flatten_df) %>%
bind_rows() %>%
#extracting Pixar from table as standalone
select(id) %>%
head(1) %>%
toString()
extracting_pixar_id
## [1] "3"
Printing Pixar id using inline code.
Pixar’s id is 3.
Code explanation:
First, I used a request to display all the Pixar options. Next, I converted the results to a table, then to a string to focus on Pixar’s id.
Observations:
There were three different names which returned from “Pixar” search query, namely:
All of above’s origin countries are either US or Canada.
Now that we have the ID of Pixar, we should be able to find all the movies they have worked on. Write a query to get all the Pixar movies and sort them by descending revenue. The result will be given to you as a JSON (parsed to a list by {httr}). Convert this list to a tibble so you have one row per film and one column per interesting piece of information. Show the query and the tibble in your report.
Retrieving all Pixar movies.
Testing query in Movie db.
Extracting all Pixar movies using API request:
Using query with API key in Insomnia to extract all Pixar movies
Extracting all Pixar movies request
*There are 7 result pages
Creating vector to store every page number which displays Pixar movies.
pixar_movies_pages <- c(
1:
7
)
pixar_movies_pages
## [1] 1 2 3 4 5 6 7
Generating API requests for all 7 Pixar results pages.
Creating table containing all Pixar movies.
pixar_movies_table <- pixar_movies_requests %>%
map(req_perform) %>%
map(resp_body_json) %>%
# View() %>%
map(pluck("results")) %>%
flatten_df() %>%
select(-genre_ids) %>%
#unnest(genre_ids) %>%
#REMEMBER TO UNNEST🪺 "genre_ids" column
unique() %>%
#arrange(title) %>%
select("id",
"original_title",
"title",
"overview",
"release_date",
"original_language",
#"genre_ids",
"popularity",
"backdrop_path",
"poster_path",
"video",
"adult",
"vote_average",
"vote_count")
# filter(vote_count == max(vote_count))
# select(original_title)
pixar_movies_table
Hints:
To find out which parameters you need to use for your query, go again to the documentation for the /discover/movies endpoint.
Have a close look at the keys in your list. You will notice that the API sends “paginated” results (i.e., look at these page and total_pages keys). It means that you never get more than x results at a time (at the time of this writing, this API sends 20 results at a time). Paginated APIs are extremely common as administrators don’t want users to send queries that would require a ton of data and block the service for others for a long time. If you want to get the other pages, you need to play with the page parameter in your URL. Further, consider that if you want to repeat the same query over and over for different pages, purrr::map() is a useful function.
Code explanation:
First, I created a variable “pixar_movies_pages” to store all the pages which would display Pixar movie results. Second, I used purrr:map to display all the api requests which would display the pages results. Then I converted the api requests results into a table.
Observations:
Pixar has worked on 138 movies in total.
The movies with the lowest vote counts of 0 are:
The movie holding highest vote counts is Inside Out with 22 273 counts.
You may know that Pixar was acquired by Disney in 2006 after they had already been collaborating on films for more than a decade. For the last part of the report, we will look into whether this was a smart strategic decision by Disney by comparing the popularity of both Disney and Pixar films that came out from 2006 onwards.
Extracting “Walt Disney Pictures” in the USA id from Moviedb
“Walt Disney Pictures” in the USA company query
“Walt Disney Pictures” in the USA api request
Extracting “Walt Disney Pictures” in the USA id
Walt_Disney_Pictures__US_id <- Walt_Disney_Pictures__US_req %>%
resp_body_json() %>%
pluck("results") %>%
map(extract, c("id",
"name",
"origin_country")) %>%
#ONLY resp_body_json or resp_body_string would work, depending on file type
map(flatten_df) %>%
bind_rows() %>%
filter(name == "Walt Disney Pictures" &
origin_country == "US") %>%
select(id) %>%
toString()
Walt_Disney_Pictures__US_id
## [1] "2"
“Walt Disney Pictures” in the USA id is 2. >>apis are dynamic, meaning values may return strange results, as witnessed with Walt Disney Pictures id above.
Creating vector to store every page number which displays Walt Disney Productions films. Range 1-11 was determined as page 1 is first page and 11 last page is from “total_pages” in api request result.
Walt_Disney_Pictures__US_2006_onwards_pages <- c(
1:
11
)
Walt_Disney_Pictures__US_2006_onwards_pages
## [1] 1 2 3 4 5 6 7 8 9 10 11
Walt_Disney_Pictures__US_2006_onwards_pages, request
--url 'https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&primary_release_date.gte=2006-01-01&primary_release_date.lte=2024-12-31&sort_by=primary_release_date.desc&with_companies=2' \
Generating API requests for Walt Disney Productions films results pages.
req tst:
--url 'https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&primary_release_date.gte=2006-01-01&primary_release_date.lte=2024-12-31&sort_by=primary_release_date.asc&with_companies=2' \
--url 'https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=1&primary_release_date.gte=2006-01-01&primary_release_date.lte=2024-12-31&sort_by=primary_release_date.desc&with_companies=2' \
Creating “Walt_Disney_Pictures__US_2006_onwards_table”
Walt_Disney_Pictures__US_2006_onwards_table <- Walt_Disney_Pictures__US_2006_onwards_req %>%
map(req_perform) %>%
map(resp_body_json) %>%
# View() %>%
map(pluck("results")) %>%
flatten_df() %>%
select(-genre_ids) %>%
#unnest(genre_ids) %>%
#REMEMBER TO UNNEST🪺 "genre_ids" column
unique() %>%
arrange(release_date) %>%
select("id",
"original_title",
"title",
"overview",
"release_date",
"original_language",
#"genre_ids",
"popularity",
"backdrop_path",
"poster_path",
"video",
"adult",
"vote_average",
"vote_count") %>%
filter(vote_count >= 50) %>%
mutate("company" = "disney")
# "total_vote_average" = mean(vote_average)) %>%
# select(company, total_vote_average) %>%
# unique()
Walt_Disney_Pictures__US_2006_onwards_table
Creating vector to store every page number which displays Pixar films. Range 1-5 was determined as page 1 is first page and 5 last page is from “total_pages” in api request result.
Pixar__US_2006_onwards_pages <- c(
1:
5
)
Pixar__US_2006_onwards_pages
## [1] 1 2 3 4 5
Pixar__US_2006_onwards_pages, request:
Generating API requests for Pixar films results pages.
Creating “Pixar__US_2006_onwards_table”
Pixar__US_2006_onwards_table <- Pixar__US_2006_onwards_pages_req %>%
map(req_perform) %>%
map(resp_body_json) %>%
# View() %>%
map(pluck("results")) %>%
flatten_df() %>%
select(-genre_ids) %>%
#unnest(genre_ids) %>%
#REMEMBER TO UNNEST🪺 "genre_ids" column
unique() %>%
arrange(release_date) %>%
select("id",
"original_title",
"title",
"overview",
"release_date",
"original_language",
#"genre_ids",
"popularity",
"backdrop_path",
"poster_path",
"video",
"adult",
"vote_average",
"vote_count") %>%
filter(vote_count >= 50) %>%
mutate("company" = "pixar")
#"total_vote_average" = mean(vote_average)) %>%
#select(company, total_vote_average) %>%
#unique()
# filter(vote_count == max(vote_count))
# select(original_title)
Pixar__US_2006_onwards_table
Below reveals Pixar movies to be exiled from Disney table
pixds <- inner_join(Walt_Disney_Pictures__US_2006_onwards_table,
Pixar__US_2006_onwards_table,
by = c("id",
"original_title",
"title",
"overview",
"release_date",
"original_language",
"popularity",
"backdrop_path",
"poster_path",
"video",
"adult",
"vote_average",
"vote_count") )
pixds
Filtering Pixar movies from Disney table Removing replicas from Disney table
#remove below from Walt_Disney_Pictures__US_2006_onwards_table
filtered_Walt_Disney_Pictures__US_2006_onwards_table <- Walt_Disney_Pictures__US_2006_onwards_table %>% filter(original_title != "WALL·E" ,
original_title != "Presto",
original_title != "Tokyo Mater",
original_title != "Toy Story 3",
original_title != "Day & Night",
original_title != "Cars 2",
original_title != "Brave",
original_title != "The Legend of Mor'du",
original_title != "Monsters University",
original_title != "Toy Story of Terror!",
original_title != "Toy Story That Time Forgot",
original_title != "Inside Out",
original_title != "The Good Dinosaur",
original_title != "Piper",
original_title != "Finding Dory",
original_title != "Coco",
original_title != "Incredibles 2",
original_title != "Bao",
original_title != "Auntie Edna",
original_title != "Toy Story 4",
original_title != "Lamp Life",
original_title != "Onward",
original_title != "Out",
original_title != "Soul",
original_title != "22 vs. Earth",
original_title != "Luca",
original_title != "Ciao Alberto",
original_title != "Turning Red",
original_title != "Lightyear",
original_title != "Elemental",
original_title != "Inside Out 2")
filtered_Walt_Disney_Pictures__US_2006_onwards_table
merge_dis_pix <- Pixar__US_2006_onwards_table %>%
full_join(filtered_Walt_Disney_Pictures__US_2006_onwards_table,
by = c("company",
"vote_average",
"id",
"original_title",
"title",
"overview",
"release_date",
"original_language",
"popularity",
"backdrop_path",
"poster_path",
"video",
"adult",
"vote_count"))
merge_dis_pix
Drawing box-plot to compare Pixar and Disney films vote averages using box-plots.
vote_average_box_plots <- ggplot(data = merge_dis_pix,
mapping = aes(x = company,
y = vote_average,
#color=vote_average
fill = company
)) +
geom_boxplot(color = "#2D282B") +
# scale_fill_manual(values = c("#FBDB92"))+
labs(title = "Box-plot displaying total average vote counts of Pixar and Disney films",
subtitle = "Comparing Pixar and Disney films popularity using box-plots",
caption = "Figure 4.1" ) +
scale_fill_manual(values = c("#EB9DB6",
"#C086A7")) +
theme_gray() +
theme(axis.text.x = element_text(angle = 360,
hjust = 1,
size = 7),
axis.title = element_text(family = "playpen_sans"),
title = element_text(family = "playpen_sans"),
axis.text = element_text(family = "playpen_sans"),
panel.background = element_rect(fill = "#F6E5E2"),
legend.background = element_rect(fill = "#FCFAF2"),
plot.background = element_rect(fill = "#F6DBE1"))
vote_average_box_plots
#geom_jitter()
After writing down your initial remarks based on the box-plot, state a statistical hypothesis and use a t-test to compare the average popularity for the two groups statistically. What is your conclusion? Do the test results confirm your observations? Was it a smart decision by Disney to acquire Pixar?
Initial remarks based on the box-plot:
It is evident by Figure 4.1, Pixar films from 2006 onwwards are on average more popular than Disney films.
Stating a statistical hypothesis:
According to Figure 4.1, Pixar films from 2006 onwards are on average more popular than Disney films.
If above statement is true, what is the probability of a difference in average popularity of movies between the two companies:
T-TEST to compare the average popularity for the two groups statistically
t_test_av_pop_dis_pix <- merge_dis_pix %>%
t_test(vote_average~ company,
# order = c("versicolor", "setosa"),
var.equal = FALSE)
## Warning: The statistic is based on a difference or ratio; by default, for
## difference-based statistics, the explanatory variable is subtracted in the
## order "disney" - "pixar", or divided in the order "disney" / "pixar" for
## ratio-based statistics. To specify this order yourself, supply `order =
## c("disney", "pixar")`.
t_test_av_pop_dis_pix
What is your conclusion?
My conclusion is Pixar films from 2006 onwards are on average more popular than Disney films.
Do the test results confirm your observations?
Yes, the test results confirm my observations, since p-value reads “0.03906208”, meaning the p value is lower than 0.07 (using 7% cut-off point), ensuring the difference in movie average popularity from both companies is statistically significant.
Was it a smart decision by Disney to acquire Pixar?
Yes, since Pixar films are more popular.
Code explanation:
First, I extracted “Walt Disney Pictures” in the USA id. Next, I used Insomnia to unveil the total pages which would display results for Disney and Pixar films. Thereafter, I mapped the API pages for each company to generate the api requests for each page. Next, I created tables to store the movies for each company from 2006 till present. After, I performed the t-test.
Observations:
According to Figure 4.1, Pixar’s films are on average more popular than Disney’s. Not certain the ratio is fair since Disney has 206 films and Pixar has 93.
Use the horizontal scroll-bar to navigate through series.
EPFL Extension School:
Elements of Data Science, Foundations of Data Science
Cover page image: https://www.freepik.com/premium-vector/castle-with-majestic-palace-architecture-fairytale-like-forest-scenery-cartoon-illustration_24542800.htm
Part 1.a
Unveiling movie genre ids https://www.themoviedb.org/talk/5daf6eb0ae36680011d7e6ee
Part 2
Extracting Pixar’s id. https://developer.themoviedb.org/reference/search-company
themovidedb.org
Part 3
Pixar lamp gif https://giphy.com/gifs/disneypixar-pixar-disney-303eg4x9WRTNK
Series images sources:
Merlin: https://www.heyuguys.com/merlin-season-4-dvd-review/
House of Anubis https://www.rottentomatoes.com/tv/house_of_anubis/s01
Haunted Hathaways https://www.imdb.com/title/tt2535732/reviews/
The Troop https://m.imdb.com/title/tt1131750/plotsummary/
The Elephant Princess https://trakt.tv/shows/the-elephant-princess/seasons/1
Note: report 3 instructs to use moviedb site for assignment, meaning it’s ok to use site for generating api requests: “Once you have provided input for all parameters you need for your query, you can click on “Try It” on the right-hand side to see the response. This is very useful to play around and get a feeling of how the queries can look in your solution for this report.”
“We send the request by clicking on “Try It!” to see the response and get the ID of the actor.” You’re supposed to use the MovieDB api request page to write your requests. The course encourages so.
Before submitting your project, make sure you have completed the following tasks:
Have you responded to all the questions listed in the reports?
Have you written your interpretation of the results?
Does your repository contain one .Rmd file per report?
Does your report knit without error?
Do your plots contain a title, subtitle and readable axis titles?
Are your tables properly displayed? (e.g., using knitr::kable())
Have you cited any code source that you might have used to complete the
reports? (e.g., Stackoverflow)
End of Report 3