Connect Data / CSV files

ratings_df <- read.csv(
  "https://raw.githubusercontent.com/mj-nurse/mnurse-data_607/refs/heads/main/assignment-02a-movie-ratings/movie_ratings.csv",
  na.strings = c("", "NULL")
)

Table Test

# View the first six rows
head(ratings_df)
##   respondent_label                     title rating
## 1         Person 1                 The Drama      4
## 2         Person 1                   Michael      3
## 3         Person 1                 Obsession      5
## 4         Person 1                 Backrooms      4
## 5         Person 1               The Odyssey      5
## 6         Person 1 Spider-Man: Brand New Day      3
# Check the number of people, movies, and rows
length(unique(ratings_df$respondent_label))
## [1] 22
length(unique(ratings_df$title))
## [1] 6
nrow(ratings_df)
## [1] 132
# Check how many ratings are missing
sum(is.na(ratings_df$rating))
## [1] 48
## Mean Movie Rating
mean_movie_rating <- mean(ratings_df$rating, na.rm = TRUE)
mean_movie_rating
## [1] 3.75
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
movie_averages <- ratings_df %>%
  group_by(title) %>%
  summarise(
    movie_avg = mean(rating, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(
    movie_avg_minus_mean_movie = movie_avg - mean_movie_rating
  )

movie_averages
## # A tibble: 6 × 3
##   title                     movie_avg movie_avg_minus_mean_movie
##   <chr>                         <dbl>                      <dbl>
## 1 Backrooms                      3.1                      -0.65 
## 2 Michael                        3.54                     -0.212
## 3 Obsession                      3.94                      0.194
## 4 Spider-Man: Brand New Day      3.89                      0.139
## 5 The Drama                      3.58                     -0.167
## 6 The Odyssey                    4.15                      0.404
user_averages <- ratings_df %>%
  group_by(respondent_label) %>%
  summarise(
    user_avg = mean(rating, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  mutate(
    user_avg_minus_mean_movie = user_avg - mean_movie_rating
  )

user_averages <- user_averages %>%
  arrange(as.numeric(sub("Person ", "", respondent_label)))

user_averages
## # A tibble: 22 × 3
##    respondent_label user_avg user_avg_minus_mean_movie
##    <chr>               <dbl>                     <dbl>
##  1 Person 1             4                        0.25 
##  2 Person 2             3.33                    -0.417
##  3 Person 3             4.75                     1    
##  4 Person 4             4                        0.25 
##  5 Person 5             4.17                     0.417
##  6 Person 6             3.5                     -0.25 
##  7 Person 7             4.67                     0.917
##  8 Person 8             4                        0.25 
##  9 Person 9             2                       -1.75 
## 10 Person 10            4.8                      1.05 
## # ℹ 12 more rows
predicted_ratings <- ratings_df %>%
  left_join(movie_averages, by = "title") %>%
  left_join(user_averages, by = "respondent_label") %>%
  filter(is.na(rating)) %>%
  mutate(
    global_baseline_estimate =
      mean_movie_rating +
      movie_avg_minus_mean_movie +
      user_avg_minus_mean_movie
  ) %>%
  arrange(
    as.numeric(sub("Person ", "", respondent_label)),
    desc(global_baseline_estimate)
  )

predicted_ratings
##    respondent_label                     title rating movie_avg
## 1          Person 2               The Odyssey     NA  4.153846
## 2          Person 2                 The Drama     NA  3.583333
## 3          Person 2                 Backrooms     NA  3.100000
## 4          Person 3                 The Drama     NA  3.583333
## 5          Person 3                 Backrooms     NA  3.100000
## 6          Person 4               The Odyssey     NA  4.153846
## 7          Person 4                 The Drama     NA  3.583333
## 8          Person 4                   Michael     NA  3.538462
## 9          Person 4                 Backrooms     NA  3.100000
## 10         Person 6                 Obsession     NA  3.944444
## 11         Person 6                   Michael     NA  3.538462
## 12         Person 7               The Odyssey     NA  4.153846
## 13         Person 7 Spider-Man: Brand New Day     NA  3.888889
## 14         Person 7                   Michael     NA  3.538462
## 15         Person 8                 Obsession     NA  3.944444
## 16         Person 8 Spider-Man: Brand New Day     NA  3.888889
## 17         Person 8                 The Drama     NA  3.583333
## 18         Person 8                   Michael     NA  3.538462
## 19         Person 8                 Backrooms     NA  3.100000
## 20         Person 9                 The Drama     NA  3.583333
## 21         Person 9                   Michael     NA  3.538462
## 22         Person 9                 Backrooms     NA  3.100000
## 23        Person 10               The Odyssey     NA  4.153846
## 24        Person 11                 The Drama     NA  3.583333
## 25        Person 11                 Backrooms     NA  3.100000
## 26        Person 12               The Odyssey     NA  4.153846
## 27        Person 12                 Backrooms     NA  3.100000
## 28        Person 14               The Odyssey     NA  4.153846
## 29        Person 14                 The Drama     NA  3.583333
## 30        Person 14                   Michael     NA  3.538462
## 31        Person 14                 Backrooms     NA  3.100000
## 32        Person 15               The Odyssey     NA  4.153846
## 33        Person 15                 Obsession     NA  3.944444
## 34        Person 15 Spider-Man: Brand New Day     NA  3.888889
## 35        Person 15                 Backrooms     NA  3.100000
## 36        Person 16                 The Drama     NA  3.583333
## 37        Person 18                   Michael     NA  3.538462
## 38        Person 19                 Obsession     NA  3.944444
## 39        Person 19                 The Drama     NA  3.583333
## 40        Person 19                   Michael     NA  3.538462
## 41        Person 19                 Backrooms     NA  3.100000
## 42        Person 20               The Odyssey     NA  4.153846
## 43        Person 20 Spider-Man: Brand New Day     NA  3.888889
## 44        Person 20                 The Drama     NA  3.583333
## 45        Person 20                 Backrooms     NA  3.100000
## 46        Person 21               The Odyssey     NA  4.153846
## 47        Person 21                   Michael     NA  3.538462
## 48        Person 21                 Backrooms     NA  3.100000
##    movie_avg_minus_mean_movie user_avg user_avg_minus_mean_movie
## 1                   0.4038462 3.333333                -0.4166667
## 2                  -0.1666667 3.333333                -0.4166667
## 3                  -0.6500000 3.333333                -0.4166667
## 4                  -0.1666667 4.750000                 1.0000000
## 5                  -0.6500000 4.750000                 1.0000000
## 6                   0.4038462 4.000000                 0.2500000
## 7                  -0.1666667 4.000000                 0.2500000
## 8                  -0.2115385 4.000000                 0.2500000
## 9                  -0.6500000 4.000000                 0.2500000
## 10                  0.1944444 3.500000                -0.2500000
## 11                 -0.2115385 3.500000                -0.2500000
## 12                  0.4038462 4.666667                 0.9166667
## 13                  0.1388889 4.666667                 0.9166667
## 14                 -0.2115385 4.666667                 0.9166667
## 15                  0.1944444 4.000000                 0.2500000
## 16                  0.1388889 4.000000                 0.2500000
## 17                 -0.1666667 4.000000                 0.2500000
## 18                 -0.2115385 4.000000                 0.2500000
## 19                 -0.6500000 4.000000                 0.2500000
## 20                 -0.1666667 2.000000                -1.7500000
## 21                 -0.2115385 2.000000                -1.7500000
## 22                 -0.6500000 2.000000                -1.7500000
## 23                  0.4038462 4.800000                 1.0500000
## 24                 -0.1666667 5.000000                 1.2500000
## 25                 -0.6500000 5.000000                 1.2500000
## 26                  0.4038462 4.000000                 0.2500000
## 27                 -0.6500000 4.000000                 0.2500000
## 28                  0.4038462 4.500000                 0.7500000
## 29                 -0.1666667 4.500000                 0.7500000
## 30                 -0.2115385 4.500000                 0.7500000
## 31                 -0.6500000 4.500000                 0.7500000
## 32                  0.4038462 4.500000                 0.7500000
## 33                  0.1944444 4.500000                 0.7500000
## 34                  0.1388889 4.500000                 0.7500000
## 35                 -0.6500000 4.500000                 0.7500000
## 36                 -0.1666667 3.200000                -0.5500000
## 37                 -0.2115385 2.800000                -0.9500000
## 38                  0.1944444 4.500000                 0.7500000
## 39                 -0.1666667 4.500000                 0.7500000
## 40                 -0.2115385 4.500000                 0.7500000
## 41                 -0.6500000 4.500000                 0.7500000
## 42                  0.4038462 3.500000                -0.2500000
## 43                  0.1388889 3.500000                -0.2500000
## 44                 -0.1666667 3.500000                -0.2500000
## 45                 -0.6500000 3.500000                -0.2500000
## 46                  0.4038462 3.333333                -0.4166667
## 47                 -0.2115385 3.333333                -0.4166667
## 48                 -0.6500000 3.333333                -0.4166667
##    global_baseline_estimate
## 1                  3.737179
## 2                  3.166667
## 3                  2.683333
## 4                  4.583333
## 5                  4.100000
## 6                  4.403846
## 7                  3.833333
## 8                  3.788462
## 9                  3.350000
## 10                 3.694444
## 11                 3.288462
## 12                 5.070513
## 13                 4.805556
## 14                 4.455128
## 15                 4.194444
## 16                 4.138889
## 17                 3.833333
## 18                 3.788462
## 19                 3.350000
## 20                 1.833333
## 21                 1.788462
## 22                 1.350000
## 23                 5.203846
## 24                 4.833333
## 25                 4.350000
## 26                 4.403846
## 27                 3.350000
## 28                 4.903846
## 29                 4.333333
## 30                 4.288462
## 31                 3.850000
## 32                 4.903846
## 33                 4.694444
## 34                 4.638889
## 35                 3.850000
## 36                 3.033333
## 37                 2.588462
## 38                 4.694444
## 39                 4.333333
## 40                 4.288462
## 41                 3.850000
## 42                 3.903846
## 43                 3.638889
## 44                 3.333333
## 45                 2.850000
## 46                 3.737179
## 47                 3.121795
## 48                 2.683333
recommendations <- predicted_ratings %>%
  group_by(respondent_label) %>%
  slice_max(
    order_by = global_baseline_estimate,
    n = 1,
    with_ties = TRUE
  ) %>%
  ungroup() %>%
  arrange(as.numeric(sub("Person ", "", respondent_label))) %>%
  select(
    respondent_label,
    title,
    global_baseline_estimate
  )

recommendations
## # A tibble: 17 × 3
##    respondent_label title       global_baseline_estimate
##    <chr>            <chr>                          <dbl>
##  1 Person 2         The Odyssey                     3.74
##  2 Person 3         The Drama                       4.58
##  3 Person 4         The Odyssey                     4.40
##  4 Person 6         Obsession                       3.69
##  5 Person 7         The Odyssey                     5.07
##  6 Person 8         Obsession                       4.19
##  7 Person 9         The Drama                       1.83
##  8 Person 10        The Odyssey                     5.20
##  9 Person 11        The Drama                       4.83
## 10 Person 12        The Odyssey                     4.40
## 11 Person 14        The Odyssey                     4.90
## 12 Person 15        The Odyssey                     4.90
## 13 Person 16        The Drama                       3.03
## 14 Person 18        Michael                         2.59
## 15 Person 19        Obsession                       4.69
## 16 Person 20        The Odyssey                     3.90
## 17 Person 21        The Odyssey                     3.74

Final Conclusion

The Global Baseline Estimate combines the Mean Movie Rating of 3.75 with each movie’s and each user’s rating relative to that average. I calculated estimates for the 48 missing ratings I had and selected the highest estimate for each person. This produced recommendations for the 17 respondents who had not seen 1 of the 6 films. The other 5 respondents had rated all 6 movies. In conclusion, The Odyssey was recommended most frequently, appearing in nine recommendations.