Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#' Advise movies based on another movie
#'
#' \code{advise.good.movie} takes as input a movie from the movie database and gives as output a number
#' of movies that are similar.
#'
#' @param similar_to character, movie title from the database.
#' @param how_many integer, how many movies to advise.
#' @param draw_scores if \code{TRUE}, draws a barplot with the similarity scores.
#' @param ... additional arguments.
#'
#' @return A list with the following elements:
#' \describe{
#' \item{\code{selected}}{movie title used to advise other movies}
#' \item{\code{to_watch}}{advised movie title(s)}
#' \item{\code{movie_ids}}{line number in the \code{movies} database of the advised movie(s)}
#' \item{\code{scores}}{similarity scores of the advised movie(s)}
#' }
#'
#'@examples
#' suggestions <- advise.good.movie(similar_to = "Interstellar", how_many = 3,
#' draw_scores = TRUE, weights = c("genre"=1, "popularity"=1, "rating"=1,
#' "production company"=1))
#'
#' @import graphics
#'
#' @export
advise.good.movie <- function(similar_to, how_many, draw_scores = FALSE, ...){
dots <- list(...)
weights <- if(is.null(dots$weights)) rep(-1, 4) else dots$weights
movies <- moviesdemo::movies
names(weights) <- c("genre", "popularity", "rating", "production company")
movie <- match.arg(similar_to, movies$title)
if(!isTRUE(is.numeric(how_many) & (length(how_many) == 1))) {
stop("Argument 'how_many' should be a number...")
}
for(x in names(weights)){
index <- which(names(weights) == x)
while(weights[index] < 0){
weight <- readline(paste0("From 0 to 5, how important is the ", x, "?"))
weight <- (if(isTRUE((as.numeric(weight) %in% 0:5) & (length(weight) == 1))){
as.numeric(weight) } else -1)
if(weight < 0){
message("Try again, please provide an integer between 0 and 5...")
}
weights[index] <- weight
}
}
indices <- (1:dim(movies)[1])[-which(movies$title == movie)]
genre <- c(scale(log(sapply(indices, function(i) sim.genres(movie, movies$title[i])) + 0.01)))
pop <- c(scale(log(movies$popularity[indices] + 0.01)))
rating <- c(scale(movies$vote[indices]))
producer <- c(scale(log(sapply(indices, function(i) sim.producers(movie, movies$title[i])) + 0.01)))
total_scores <- weights[1] * genre + (weights[2] / 4) * pop +
(weights[3] / 4) * rating + (weights[4] / 2) * producer
top_indices <- indices[order(total_scores, decreasing = T)[1:how_many]]
scores <- sort(total_scores, decreasing = T)[1:how_many]
to_watch <- movies$title[top_indices]
if (draw_scores) {
names(scores) <- to_watch
m <- barplot(scores, ylim=c(0, ceiling(max(scores))), col = "blue", main = "Movie scores")
text(m, scores * 0.9, labels = round(scores, 2), col = "white")
}
return.list <- list(selected = movie, to_watch = to_watch, movie_ids = top_indices, scores = scores)
class(return.list) <- "advice"
return(return.list)
}