Week 3A Global Baseline Estimate

Author

Sarah Abdelrahman

DATA 607 — Data Acquisition & Management

M.S. in Data Science | CUNY School of Professional Studies

Student: Sarah Abdelrahman
Instructor: Professor Darwin Gomez

Introduction

For this assignment, I will use the movie-rating data collected in Week 2A to create a simple non-personalized movie recommendation system using the Global Baseline Estimate algorithm.

The Global Baseline Estimate uses the overall average rating, the user’s average rating, and the movie’s average rating to estimate a missing rating.

Setup

library(dplyr)

Create the Movie Rating Data

I used the same movie-rating data from my Week 2A assignment.

Missing values represent movies that a participant did not watch.

ratings <- data.frame(
  person = c(
    rep("Person 1", 6),
    rep("Person 2", 6),
    rep("Person 3", 6),
    rep("Person 4", 6),
    rep("Person 5", 6)
  ),

  movie = rep(
    c(
      "Inside Out 2",
      "Deadpool & Wolverine",
      "Dune: Part Two",
      "Wicked",
      "Moana 2",
      "The Wild Robot"
    ),
    5
  ),

  rating = c(
    5, 4, 4, NA, 5, 4,
    4, NA, 5, 4, 3, NA,
    5, 3, NA, 5, 4, 5,
    4, 4, 5, NA, 4, 5,
    NA, 5, 4, 4, 5, 4
  )
)

ratings
     person                movie rating
1  Person 1         Inside Out 2      5
2  Person 1 Deadpool & Wolverine      4
3  Person 1       Dune: Part Two      4
4  Person 1               Wicked     NA
5  Person 1              Moana 2      5
6  Person 1       The Wild Robot      4
7  Person 2         Inside Out 2      4
8  Person 2 Deadpool & Wolverine     NA
9  Person 2       Dune: Part Two      5
10 Person 2               Wicked      4
11 Person 2              Moana 2      3
12 Person 2       The Wild Robot     NA
13 Person 3         Inside Out 2      5
14 Person 3 Deadpool & Wolverine      3
15 Person 3       Dune: Part Two     NA
16 Person 3               Wicked      5
17 Person 3              Moana 2      4
18 Person 3       The Wild Robot      5
19 Person 4         Inside Out 2      4
20 Person 4 Deadpool & Wolverine      4
21 Person 4       Dune: Part Two      5
22 Person 4               Wicked     NA
23 Person 4              Moana 2      4
24 Person 4       The Wild Robot      5
25 Person 5         Inside Out 2     NA
26 Person 5 Deadpool & Wolverine      5
27 Person 5       Dune: Part Two      4
28 Person 5               Wicked      4
29 Person 5              Moana 2      5
30 Person 5       The Wild Robot      4

Check Missing Ratings

I first checked how many ratings are completed and how many are missing.

ratings %>%
  summarise(
    total_observations = n(),
    completed_ratings = sum(!is.na(rating)),
    missing_ratings = sum(is.na(rating))
  )
  total_observations completed_ratings missing_ratings
1                 30                24               6

There are 30 possible ratings, with 24 completed ratings and 6 missing ratings.

Global Mean Rating

First, I calculated the average of all completed movie ratings.

global_mean <- mean(
  ratings$rating,
  na.rm = TRUE
)

global_mean
[1] 4.333333

The global mean rating is approximately 4.33.

User Average Ratings

Next, I calculated the average rating given by each participant.

user_averages <- ratings %>%
  group_by(person) %>%
  summarise(
    user_average = mean(
      rating,
      na.rm = TRUE
    ),
    .groups = "drop"
  )

user_averages
# A tibble: 5 × 2
  person   user_average
  <chr>           <dbl>
1 Person 1          4.4
2 Person 2          4  
3 Person 3          4.4
4 Person 4          4.4
5 Person 5          4.4

Movie Average Ratings

I also calculated the average rating for each movie.

movie_averages <- ratings %>%
  group_by(movie) %>%
  summarise(
    movie_average = mean(
      rating,
      na.rm = TRUE
    ),
    .groups = "drop"
  )

movie_averages
# A tibble: 6 × 2
  movie                movie_average
  <chr>                        <dbl>
1 Deadpool & Wolverine          4   
2 Dune: Part Two                4.5 
3 Inside Out 2                  4.5 
4 Moana 2                       4.2 
5 The Wild Robot                4.5 
6 Wicked                        4.33

Calculate Differences from the Global Mean

Following the Global Baseline Estimate spreadsheet, I calculated how far each user’s average and each movie’s average are from the global mean.

user_averages <- user_averages %>%
  mutate(
    user_difference =
      user_average - global_mean
  )

movie_averages <- movie_averages %>%
  mutate(
    movie_difference =
      movie_average - global_mean
  )

user_averages
# A tibble: 5 × 3
  person   user_average user_difference
  <chr>           <dbl>           <dbl>
1 Person 1          4.4          0.0667
2 Person 2          4           -0.333 
3 Person 3          4.4          0.0667
4 Person 4          4.4          0.0667
5 Person 5          4.4          0.0667
movie_averages
# A tibble: 6 × 3
  movie                movie_average movie_difference
  <chr>                        <dbl>            <dbl>
1 Deadpool & Wolverine          4              -0.333
2 Dune: Part Two                4.5             0.167
3 Inside Out 2                  4.5             0.167
4 Moana 2                       4.2            -0.133
5 The Wild Robot                4.5             0.167
6 Wicked                        4.33            0    

Global Baseline Estimate

The Global Baseline Estimate is calculated as:

Global Mean + Movie Difference + User Difference

I joined the user and movie averages with the original ratings and calculated an estimated rating for each user and movie combination.

baseline_estimates <- ratings %>%
  left_join(
    user_averages,
    by = "person"
  ) %>%
  left_join(
    movie_averages,
    by = "movie"
  ) %>%
  mutate(
    estimated_rating =
      global_mean +
      movie_difference +
      user_difference
  )

baseline_estimates
     person                movie rating user_average user_difference
1  Person 1         Inside Out 2      5          4.4      0.06666667
2  Person 1 Deadpool & Wolverine      4          4.4      0.06666667
3  Person 1       Dune: Part Two      4          4.4      0.06666667
4  Person 1               Wicked     NA          4.4      0.06666667
5  Person 1              Moana 2      5          4.4      0.06666667
6  Person 1       The Wild Robot      4          4.4      0.06666667
7  Person 2         Inside Out 2      4          4.0     -0.33333333
8  Person 2 Deadpool & Wolverine     NA          4.0     -0.33333333
9  Person 2       Dune: Part Two      5          4.0     -0.33333333
10 Person 2               Wicked      4          4.0     -0.33333333
11 Person 2              Moana 2      3          4.0     -0.33333333
12 Person 2       The Wild Robot     NA          4.0     -0.33333333
13 Person 3         Inside Out 2      5          4.4      0.06666667
14 Person 3 Deadpool & Wolverine      3          4.4      0.06666667
15 Person 3       Dune: Part Two     NA          4.4      0.06666667
16 Person 3               Wicked      5          4.4      0.06666667
17 Person 3              Moana 2      4          4.4      0.06666667
18 Person 3       The Wild Robot      5          4.4      0.06666667
19 Person 4         Inside Out 2      4          4.4      0.06666667
20 Person 4 Deadpool & Wolverine      4          4.4      0.06666667
21 Person 4       Dune: Part Two      5          4.4      0.06666667
22 Person 4               Wicked     NA          4.4      0.06666667
23 Person 4              Moana 2      4          4.4      0.06666667
24 Person 4       The Wild Robot      5          4.4      0.06666667
25 Person 5         Inside Out 2     NA          4.4      0.06666667
26 Person 5 Deadpool & Wolverine      5          4.4      0.06666667
27 Person 5       Dune: Part Two      4          4.4      0.06666667
28 Person 5               Wicked      4          4.4      0.06666667
29 Person 5              Moana 2      5          4.4      0.06666667
30 Person 5       The Wild Robot      4          4.4      0.06666667
   movie_average movie_difference estimated_rating
1       4.500000        0.1666667         4.566667
2       4.000000       -0.3333333         4.066667
3       4.500000        0.1666667         4.566667
4       4.333333        0.0000000         4.400000
5       4.200000       -0.1333333         4.266667
6       4.500000        0.1666667         4.566667
7       4.500000        0.1666667         4.166667
8       4.000000       -0.3333333         3.666667
9       4.500000        0.1666667         4.166667
10      4.333333        0.0000000         4.000000
11      4.200000       -0.1333333         3.866667
12      4.500000        0.1666667         4.166667
13      4.500000        0.1666667         4.566667
14      4.000000       -0.3333333         4.066667
15      4.500000        0.1666667         4.566667
16      4.333333        0.0000000         4.400000
17      4.200000       -0.1333333         4.266667
18      4.500000        0.1666667         4.566667
19      4.500000        0.1666667         4.566667
20      4.000000       -0.3333333         4.066667
21      4.500000        0.1666667         4.566667
22      4.333333        0.0000000         4.400000
23      4.200000       -0.1333333         4.266667
24      4.500000        0.1666667         4.566667
25      4.500000        0.1666667         4.566667
26      4.000000       -0.3333333         4.066667
27      4.500000        0.1666667         4.566667
28      4.333333        0.0000000         4.400000
29      4.200000       -0.1333333         4.266667
30      4.500000        0.1666667         4.566667

Predict Missing Ratings

For the recommendation system, I only need the movies that participants did not already rate.

missing_predictions <- baseline_estimates %>%
  filter(is.na(rating)) %>%
  select(
    person,
    movie,
    user_average,
    movie_average,
    estimated_rating
  )

missing_predictions
    person                movie user_average movie_average estimated_rating
1 Person 1               Wicked          4.4      4.333333         4.400000
2 Person 2 Deadpool & Wolverine          4.0      4.000000         3.666667
3 Person 2       The Wild Robot          4.0      4.500000         4.166667
4 Person 3       Dune: Part Two          4.4      4.500000         4.566667
5 Person 4               Wicked          4.4      4.333333         4.400000
6 Person 5         Inside Out 2          4.4      4.500000         4.566667

Person 2 Movie Predictions

Person 2 did not rate two movies:

  • Deadpool & Wolverine
  • The Wild Robot

I compared the estimated ratings for these two movies.

person2_predictions <- missing_predictions %>%
  filter(person == "Person 2") %>%
  arrange(
    desc(estimated_rating)
  )

person2_predictions
    person                movie user_average movie_average estimated_rating
1 Person 2       The Wild Robot            4           4.5         4.166667
2 Person 2 Deadpool & Wolverine            4           4.0         3.666667

Final Recommendation

Finally, I selected the movie with the highest Global Baseline Estimate for Person 2.

recommendation <- person2_predictions %>%
  slice_max(
    estimated_rating,
    n = 1,
    with_ties = FALSE
  )

recommendation
    person          movie user_average movie_average estimated_rating
1 Person 2 The Wild Robot            4           4.5         4.166667

The estimated rating for The Wild Robot is approximately 4.17, while the estimated rating for Deadpool & Wolverine is approximately 3.67.

Therefore, the recommended movie for Person 2 is The Wild Robot.

Conclusion

The Global Baseline Estimate provides a simple non-personalized method for estimating missing movie ratings.

The method uses the overall average rating together with differences in each user’s rating behavior and each movie’s average rating.

For Person 2, the model estimated a higher rating for The Wild Robot, so this movie was selected as the final recommendation.