This assignment is to be completed in groups of 3-4. Further, all students in your group need to be assigned to the same R tutorial group (Friday’s tutorial). You can sign yourself up for a group on Canvas. Please do so You can use the Discussion Board in Canvas if you do not have a group yet or if your group is incomplete.
The assignment has 5 parts, and each part corresponds to the course material of that week (with the exclusion of week 6, for which there is no R programming material).
You are supposed to hand in these assignments on Canvas at the following dates:
The R tutorials (each Friday) will consist of two halves. During the first half, you will discuss the tutorial exercises. These can be downloaded separately from Canvas. During the second half, you can work on this graded assignment within your own group. The purpose is that you find out how to work with R for doing statistical analyses by yourself. The tutorial exercises are meant to teach you basic commands to get you started, but to answer the problem sets in this assignment, you might need to research your own solutions, and use functions and commands not described in the tutorial exercises. Learning how to solve your own research problems is integral part of learning R. When you and your group get stuck on how to approach an exercise, the hierarchy in finding your way is as follows:
The use of generative AI is permitted and may result in a grade of 0. See the AI protocol in the course manual for details.
To answer the assignment, you can simply fill out this R markdown document. There are designated places which you can fill with R code. There are also designated spaces for you to answer each question. Often, the structure of an answer will be as follows. First, you type the R code in the designated box. This will show how you analyzed the data to get the answer to the question. Below the box for the R code, you will then summarize your answer to the question, i.e. what are the conclusions that you draw from the data analysis?
When handing in, you are supposed to submit this .Rmd file, and a knitted version of this document. You can knit this document to pdf, word, or html. Knitting to pdf requires you to have a .tex distribution installed on your computer. Knitting to Word requires you to have Word installed.
The exercises are designed such that you should be able to finish the majority of them during the tutorial each week. If you are not able to finish them fully during that time, you are expected to work on it in your own time using the computers on campus or your own device. It is best to meet as a group in-person when working together. If you want to work remotely, github is a good platform to guarantee smooth collaboration. Alternatively, you can email this .Rmd file back and forth to one another as a group, but this is not recommended as it is more cumbersome.
We encourage you to keep your code blocks, printing statements, and final answers, as short as possible. In any case, there is a page limit of 6 pages per week, which encompasses the total length of this document which consists of the questions, your coding lines, and your answers. When your answers to questions of the respective week exceed this page limit, they will not be graded, resulting in zero points.
library(readr)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ purrr 1.0.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.2 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
movies5 <- read_tsv("movies5.tsv")
## Rows: 909 Columns: 19
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: "\t"
## chr (8): keywords, original_language, title, genre, first_actor, first_act...
## dbl (10): index, budget, popularity, revenue, runtime, vote_average, vote_c...
## date (1): release_date
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(movies5)
ncol(movies5)
## [1] 19
nrow(movies5)
## [1] 909
We can conclude that the data set has ncol(movies5) variables, which is 19, and nrow(movies5) subjects, which is 909. Each movie has different data on the same subjects, such as budget, revenue, genre, etc.
sapply(movies5, class)
## index budget keywords original_language
## "numeric" "numeric" "character" "character"
## title popularity release_date revenue
## "character" "numeric" "Date" "numeric"
## runtime vote_average vote_count genre
## "numeric" "numeric" "numeric" "character"
## release_year release_month release_day first_actor
## "numeric" "numeric" "numeric" "character"
## first_actor_gender director_first_name director_gender
## "character" "character" "character"
In this data set the following types of variables are present: nominal, continuous and discrete. Nominal data is data that is put in groups or labels that don’t have a natural order. An example from the data set movies 5 is original_language. Continuous variables have numbers that aren’t limited to whole numbers, an example in this data set is budget. Discrete variables are numbers you can count, no decimals, such as release_year
For each step, you should provide first all the code you used to answer the question and then formulate an answer using full sentences.
Each week consists of 1, 2, or 3 subquestions. The total amount of points you can earn per week is 20 points.
Step a
summary(movies5$revenue)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.000e+00 0.000e+00 2.548e+07 8.885e+07 1.016e+08 1.157e+09
The mean is 88.850.000, the median is 25.480.000, the min is 0 and the max is 1.157.000.000.
Step b
#Highest revenue
max_row <- movies5[which.max(movies5$revenue), ]
cat("Highest revenue film:\n")
## Highest revenue film:
cat("Title:", max_row$title, "\n")
## Title: Minions
cat("Revenue:", max_row$revenue, "\n\n")
## Revenue: 1156730962
#Lowest revenue
min_row <- movies5[which.min(movies5$revenue), ]
cat("Lowest revenue film:\n")
## Lowest revenue film:
cat("Titel:", min_row$title, "\n")
## Titel: The Brothers McMullen
cat("Revenue:", min_row$revenue, "\n")
## Revenue: 0
The highest revenue film is the Minions with a revenue of 1,156,730,962. The lowest revenue film was The Brothers McMullen with a revenue of 0.
Step c
ggplot(movies5, aes(x=revenue))+
geom_histogram()+
labs(title = "Revenue movies5",
x = "Revenue",
y = "Frequency")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
In this histogram you can see that the highest frequencies of revenue are at the start of the histogram, meaning at the lower revenues. This tells us that it is very hard to make a high revenue from movies and that most of them stay at the “lower” revenues.
Step d
movies5 = mutate(movies5, log_revenue = log(movies5$revenue))
mean(movies5$log_revenue)
## [1] -Inf
Because the logarithm of 0 is undefined in math, R will also give you a -Inf with movies where the revenue is 0. This is also why the mean returns with -Inf
Step e
movies5$log_revenue[movies5$log_revenue == -Inf] = NA
mean(movies5$log_revenue, na.rm = TRUE)
## [1] 17.54381
ggplot(movies5, aes(x=log_revenue))+
geom_histogram()+
labs(Title = "Log revenue of movies",
x = "Log revenue",
y = "frequency")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 257 rows containing non-finite outside the scale range
## (`stat_bin()`).
Now the mean of log_revenue is 17.54381.
Step f
library(e1071)
#revenue
cat("Revenue:")
## Revenue:
cat("Skewness:", skewness(movies5$revenue, na.rm = TRUE), "\n")
## Skewness: 3.175794
cat("Kurtosis:", kurtosis(movies5$revenue, na.rm = TRUE), "\n")
## Kurtosis: 11.79448
#log_revenue
cat("Log Revenue:")
## Log Revenue:
cat("Skewness:", skewness(movies5$log_revenue, na.rm = TRUE), "\n")
## Skewness: -2.509085
cat("Kurtosis:", kurtosis(movies5$log_revenue, na.rm = TRUE), "\n")
## Kurtosis: 12.36784
For revenue, skewness = 3.18 and kurtosis = 11.79. This indicates a highly right-skewed distribution with heavy tails, meaning most movies earn low revenue while a few earn extremely high revenue. For log_revenue, skewness = -2.51 and kurtosis = 12.37. The log transformation shifts the distribution to the left, showing that most movies cluster at higher log-revenue values, but extreme low values still exist. These values match the histograms: the revenue histogram is right-skewed with a long tail, and the log_revenue histogram is left-skewed and peaked, confirming the presence of outliers and heavy tails.:
1 Is your dataset movies5.tsv the full population, or is it a sample of a larger population? If the latter, how would you describe the full population?
This is a sample of a larger population. The data set shows a sample of films and not, if it were the full population, all feature films produced globally.
2 For this question, you will assume that your data set is the full population.
Step a
mean(movies5$vote_average)
## [1] 6.011001
The mean of vote_average is 6.011
The mean of vote_average of movies5 is 6.011.
Step b
set.seed(1)
movies_sample = movies5[sample(nrow(movies5),25),]
mean(movies_sample$vote_average)
## [1] 6.132
The mean of vote_average at the random sample is 6.132
The mean of vote_average at the random sample is higher then the mean of the average of movies5.
Step c
sample_means = numeric(100)
for (i in 1:100) {
movies_sample = movies5[sample(nrow(movies5),25),]
sample_means[i] = mean(movies_sample$vote_average)
}
print(sample_means)
## [1] 6.140 5.384 6.096 5.952 6.112 6.380 5.684 6.308 6.300 6.100 5.748 6.568
## [13] 5.916 6.164 6.140 5.708 6.024 6.272 6.080 6.120 6.036 5.552 6.228 6.108
## [25] 6.096 5.980 6.464 6.008 5.944 5.744 6.060 5.764 6.340 6.000 6.000 6.312
## [37] 6.268 6.084 6.028 6.156 5.804 5.852 6.092 6.192 5.508 6.052 5.904 6.108
## [49] 5.648 5.644 6.388 5.696 6.620 6.220 6.048 6.216 5.932 6.076 6.060 6.408
## [61] 5.740 5.856 6.108 6.544 6.156 5.956 5.776 5.956 5.788 6.204 6.028 6.016
## [73] 5.956 5.872 6.288 6.152 5.200 6.152 6.140 5.640 6.020 6.356 6.124 6.292
## [85] 6.360 6.332 5.908 5.528 5.976 6.076 6.204 6.108 6.304 6.484 5.988 6.152
## [97] 6.000 6.040 6.052 6.024
The vector sample_means contains 100 sample means of 25 randomly selected movies each. These values are all around the population mean of 6.011. Some sample means are slightly higher, others slightly lower. But overall they are close to the population mean of 6.011.
Step d
set.seed(25)
mean(sample_means)
## [1] 6.04692
sd(sample_means)
## [1] 0.2530006
ggplot(data.frame(sample_means), aes(x = sample_means)) +
geom_histogram() +
labs(title = "Distribution of Sample Means",
x = "Sample mean of vote_average",
y = "Frequency")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Your Answer:
The mean is 5.99 and the standard deviation is 0.23 and the shape is of the histogram is roughly bell-shaped
Step e
By the Central Limit Theorem, sample mean of vote_average with n = 25 is about normally distributed with mean ≈ 6.0 and variance ≈ 0.2. These are identical with our results in step d, where sample_means was distributed around 6.0 with spread of about 0.2 and was about normal in shape.
ggplot(movies5, aes(x = release_day)) +
geom_histogram(binwidth = 1, color = "white", linewidth = 0.5) +
scale_x_continuous(breaks = c(1, 5, 10, 15, 20, 25, 30))+
labs(title = "films released on particulair day",
x = "day of month",
y = "amount of films") +
geom_hline(yintercept = 30.3, color = "red", linewidth = 0.5)
The expectation is that the release day would follow a discrete uniform distribution, because we do not expect that it matters when I film is released. The problem with this variable is however that not every month is the same length. So we expect a uniform distribution until the 28th variable. If the release day would follow a uniform distribution, with an expected amount of days per month of 30, the mean would be 30 + 1 / 2 = 15.5 The variance would be ((30 - 1 + 1)^2 - 1) / 12 = 74.92 and the standard deviation would be 8.66. There are 909 films, so the appropriate discrete uniform distribution would be around 909 / 30 = 30.3.The variable deviates a bit from the appropriate discrete uniform distribution due to the fact that not every month has the same amount of days. Additionally, filmmakers tend to release movies on the first day of the month, which results in a higher number of films being released on the first day. Due to that, films are less released on the last day.
For the next part of the assignment, assume that the movies in your data frame are a random sample of a larger population of movies.
x <- na.omit(movies5$revenue)
n <- length(x)
mean_x <- mean(x)
standard_deviation_x <- sd(x)
error_margin <- qt(0.95, df = n - 1) * standard_deviation_x / sqrt(n)
lower <- mean_x - error_margin
upper <- mean_x + error_margin
cat("[", lower, upper,"]")
## [ 80068897 97623733 ]
The 90% confidence interval of [80,068,897 , 97,623,733] gives the range within which we are 90% confident that the true population mean revenue lies.
2
step a
table(movies5$director_gender)
##
## female male
## 82 780
In our sample,780 movies were directed by male directors and 82 movies were directed by female directors.
step b
chisq.test(table(movies5$director_gender), p=c(0.5,0.5))
##
## Chi-squared test for given probabilities
##
## data: table(movies5$director_gender)
## X-squared = 565.2, df = 1, p-value < 2.2e-16
The p-value is < 0.001. At α = 0.05 we reject the null hypothesis. Conclusion: The chance of a movie directed by a male is significantly different from that of a female.
step c
movies5$revenue_in_millions<-movies5$revenue/1000000
tapply(movies5$revenue_in_millions, movies5$director_gender, var, na.rm=TRUE)
## female male
## 18066.64 27072.45
The variance of the revenue (in millions) is: Male directors:27,072.45. Female directors:18,066.64
step d
var.test(revenue_in_millions~director_gender,data=movies5)
##
## F test to compare two variances
##
## data: revenue_in_millions by director_gender
## F = 0.66734, num df = 81, denom df = 779, p-value = 0.02301
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
## 0.4925163 0.9443006
## sample estimates:
## ratio of variances
## 0.6673442
Result:F=0.6673,df(1)=81,df(2)=779,p-value=0.023. At α=0.05 we reject the null hypothesis. Conclusion:The variance of revenues for movies direct by females is significantly different from that of movies directed by males.
3
step a
#Calculate the mean revenue per year
mean_revenue_year = movies5 %>%
group_by(release_year) %>%
summarise(
mean_revenue = mean(revenue, na.rm = TRUE)
) %>%
arrange(release_year)
print(mean_revenue_year)
## # A tibble: 27 × 2
## release_year mean_revenue
## <dbl> <dbl>
## 1 1990 62106141
## 2 1991 55638308
## 3 1992 134762267.
## 4 1993 52028323.
## 5 1994 132543419.
## 6 1995 106502867.
## 7 1996 91179763.
## 8 1997 108233528.
## 9 1998 59957441.
## 10 1999 56721515.
## # ℹ 17 more rows
ggplot(mean_revenue_year, aes(x = release_year, y = mean_revenue)) +
geom_point()+
geom_smooth(method = "lm", se = FALSE) +
labs(
title = "Mean Movie Revenue by Release Year",
x = "Release Year",
y = "Mean Revenue (in billions)"
)
## `geom_smooth()` using formula = 'y ~ x'
Looking at the graph you can see that the line of the mean revenue per year is a steep upward line. This means that newer movies tend to generate a higher mean revenue compared to older ones
step b
#first calculate the 95% CI for each year
mean_revenue_year <- movies5 %>%
group_by(release_year) %>%
summarise(
mean_revenue = mean(revenue, na.rm = TRUE),
sd_revenue = sd(revenue, na.rm = TRUE),
n_movies = n())%>%
mutate(
se = sd_revenue / sqrt(n_movies),
ci_lower = mean_revenue - 1.96 * se,
ci_upper = mean_revenue + 1.96 * se)
#Plot the graph
ggplot(mean_revenue_year, aes(x = release_year, y = mean_revenue)) +
geom_point() +
geom_errorbar(aes(ymin = ci_lower, ymax = ci_upper), width = 0.2) +
labs(
title = "Mean Movie Revenue by Release Year",
x = "Release Year",
y = "Mean Revenue (in billions)")
The scatter plot now shows release years vs mean revenue with a 95% confidence interval
step c
#There is no code necessary for this question
The reason that in certain years the confidence interval is wide can be because of different reasons. A reason could be that there is a small sample size, meaning fewer movies estimate the mean, so it is based on little information. Looking at our dataset movies5, you can also see that the older movies don’t have a large sample size (n_movies is small). Another reason could be that there is extreme volatility in revenues. Meaning that if a year has a large number of movies, the confidence interval will be wide if the revenues for that year are highly spread out.
step a
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step b
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step c
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step d
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step e
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step f
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step g
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
2
step a
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step b
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
The movie studio that you work at is releasing a new movie in 2026. It will be a Drama movie with a budget of 20,000,0000. It will have a runtime of 120 minutes.
step a
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step b
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step c
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step d
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step e
#WRITE YOUR CODE HERE
Your Answer:
Write your formulated response here.
step f
#WRITE YOUR CODE HERE