Основные + дополнительные данные

library(readr)
library(stringr)
library(tidyverse)
library(magrittr)
 
library(dplyr) 
library(tidytext) 
library(ggplot2)

movies <- read_csv("~/shared/minor2_2017/data/netflix/movie_info.csv") %>% rename(movie_id = id)
## Warning: Duplicated column names deduplicated: 'id' => 'id_1' [7]
marks_3 <- read_csv("~/shared/minor2_2017/data/netflix/groups/marks_3.csv")

# данные по актерам и режиссеру
TAD <- read_delim("~/project_databases/title_actors_directors.csv", 
    ";", escape_double = FALSE, trim_ws = TRUE)
## Warning: Missing column names filled in: 'X20' [20]
TAD = select(TAD, title, actor1_name, actor2_name, director_name, release_date)
library(lubridate)
TAD$release_date = dmy(TAD$release_date)
## Warning: 1040 failed to parse.
TAD$release_date = year(TAD$release_date)
TAD$fy = str_c(TAD$title,TAD$release_date)
TAD = select(TAD, actor1_name, actor2_name, director_name, fy)


# считаем среднюю оценку 
data = marks_3 %>% group_by(movie_id) %>% summarize(marks = mean(mark, na.rm = T))

# соеденим два датасета 
data = inner_join(data, movies)
# присоединяем год фильма
data$fy = str_c(data$title,data$year)
# присоединим 2 актеров и режиссера
data = left_join(data,TAD, by = "fy")
data$idD = as.integer(duplicated(data$movie_id))
data = filter(data, data$idD=="0")

#Удаляем все ненужные столбцы
data = select(data, -homepage, -id_1)


# добавляем Оскар
Oscar <- read_csv("~/project_databases/database.csv")
#connect
Oscar1 = select(Oscar, -Name)
Oscar2 = select(Oscar, -Film)
names(Oscar2)[5] = "Film"
OscarF = bind_rows(Oscar1,Oscar2)
#уникальный идентификатор
OscarF$fy = str_c(OscarF$Film,OscarF$Year)

data4 = left_join(data,OscarF,by="fy")
data4 = select(data4, movie_id, marks, popularity, Award, Winner)

data4$nominee = as.integer(is.na(data4$Winner))
data4$oscar = as.integer(is.na(data4$Award))

data4 %<>% mutate(prize=ifelse(data4$oscar==0 & data4$nominee==0,2,ifelse(data4$oscar==0 & data4$nominee==1,1,0)))

data4 = select(data4, movie_id, marks, popularity, prize, Award)

data4$Award[data4$prize==0] = "none"

data4$idD = as.integer(duplicated(data4))
data4 = filter(data4, data4$idD=="0")
data4 = select(data4,-idD)
data4 = data4[-458,]

data0 = select(data, movie_id, title, popularity)
data4 = left_join(data4,data0,by="movie_id")


# special data
data4Oscar <- data4 %>% group_by(movie_id) %>% summarise(Award = paste(unique(Award), collapse = ' '))
data4Oscar <- left_join(data4Oscar,data0,by="movie_id")
# выгружаем данные
#write.csv(data, "~/data_noOscar.csv")

Крутой пользователь:

top_users = marks_3 %>% count(user_id, sort=T) %>% head(n=10)

Введите фильтры для поиска:

user = sample(top_users$user_id) %>% head(n=1)

gnr <- as.character("Drama")
drc <- as.character("Adam Shankman")
act <- as.character("Ben Affleck")
osc <- as.character("Best Picture")

wrd1 <- as.character("slaughter")
wrd2 <- as.character("death")
wrd3 <- as.character("suicide")
wrd4 <- as.character("killing")
wrd5 <- as.character("war")

Подготовка данных под каждую рекомендашку

Выбираем переменные, которые пригодятся для составления матрицы схожести фильмов: здесь это жанры, популярность и дата выпуска (в финальном варианте сюда будут записаны ещё наличие наград, режиссёры, актёры)

data1 = data %>% dplyr::select(movie_id, marks, genres, popularity, release_date)

data2 = data %>% dplyr::select(movie_id, marks, popularity, director_name)

data3 = data %>% dplyr::select(movie_id, marks, popularity, actor1_name)

Сезоны

Через ifelse разобьём на сезоны, исходя из нашего предположения о наклонности производителей выпускать фильмы определённых жанров в определённые сезоны

data1 %<>% mutate(Season=ifelse(str_detect(data1$release_date, "-01|-02|-12"), "1", ifelse(str_detect(data1$release_date, "-03|-04|-05"), "2", ifelse(str_detect(data1$release_date, "-06|-07|-08"), "3", ifelse(str_detect(data1$release_date, "-09|-10|-11"), "4", NA)))))

data1$Season = as.numeric(data1$Season)

Жанры

Преобразуем жанры

library(tidyr)
source("~/shared/minor2_2017/2-tm-net/lab08-proj-data/extract_json.R") 
data1 = extract_json(df = data1, col = "genres")

Удаляем лишние переменные

data1 %<>% dplyr::select(-genres, -release_date)

Считаем матрицу схожести фильмов

rownames(data1) = data1$movie_id
data1 %<>% dplyr::select(-movie_id)
sim = lsa::cosine(t(as.matrix(data1)))

# удаляем единицы в диагональных значениях 
diag(sim) = 0

Описание. Пользователь должен будет ввести свой id; жанр фильма, который он хочет посмотреть; и слова, которые он НЕ хочет встретить в keywords к этому фильму (в идеале, и тематика фильма не должна содержать эти элементы). Таким образом, система: 1)изначально фильтрует таблицу с оценками пользователей так, что там остаются отзывы только данного пользователя, причём с МАКСИМАЛЬНОЙ для него оценкой 2)далее, система, основываюсь на матрице схожести, ищет ПОХОЖИЕ фильмы для оценённых фильмов; после этого наиболее похожие фильмы соотносятся с датасетом data
3)здесь уже отбираются фильмы указанного жанра и не содержащие указанные слова в keywords и overview 4)если пользователь не оценил ни одного фильма, то тогда ему рекомендуются ТОП-5 фильмов, отфильтрованных по жанру и не включающих указанные слова в keywords и overview

# итоговый вариант; nof = 50 - количество рекомендаций)
find_film = function(userId, genre, kw1, kw2, kw3, kw4, kw5, nof = 50){
  m = marks_3 %>% filter(user_id == userId) %>% filter(mark %in% max(mark)) %>% filter(movie_id %in% data$movie_id)                
  if (nrow(m) > 0){
    
    mostSimilar = head(sort(sim[,as.character(m$movie_id)], decreasing = T), n = 50)
    a = which(sim[,as.character(m$movie_id)] %in% mostSimilar, arr.ind = TRUE)
    rows = a %% dim(sim)[1]
    result = rownames(sim)[rows]
    data %>% filter(movie_id %in% result) %>% filter(str_detect(genres, genre)) %>% filter(!str_detect(keywords, str_c(kw1, "&", kw2, "&", kw3, "&", kw4, "&", kw5))) %>% filter(!str_detect(overview, str_c(kw1, "&", kw2, "&", kw3, "&", kw4, "&", kw5))) %>%  dplyr::select(title) %>% head(nof, title)
    
    } else {
    
    data %>% filter(str_detect(genres, genre)) %>% filter(!str_detect(keywords, str_c(kw1, "&", kw2, "&", kw3, "&", kw4, "&", kw5))) %>% filter(!str_detect(overview, str_c(kw1, "&", kw2, "&", kw3, "&", kw4, "&", kw5))) %>% top_n(nof, popularity) %>% dplyr::select(title)
      
    }
}

Если пользователь имеет аккаунт в системе: Сделаем рекомендацию для пользователя с userId = 712664, который хочет посмотреть драму, но такую, чтобы её основная тематика не касалсь слов в кавычках

a = sample(top_users$user_id) %>% head(n=1)

recGA <- find_film(user, gnr, wrd1,wrd2,wrd3,wrd4,wrd5)
# Убираем фильмы, которые пользователь уже посмотрел
recG <- recGA
recG <- left_join(recG, data, by="title")
recG <- select(recG, title, movie_id)
recG <- left_join(recG, marks_3, by="movie_id")
recG <- filter(recG, recG$user_id==a)

recGA %<>% filter(!title %in% recG$title)

Если пользователь никогда не ставил оценки до этого, пусть в userId пишет “0” (так система сразу перенесёт его ко второй части функции)

find_film(0, gnr, wrd1,wrd2,wrd3,wrd4,wrd5)
## # A tibble: 50 x 1
##                         title
##                         <chr>
##  1                Wild Things
##  2                    Solaris
##  3              Trainspotting
##  4               Irreversible
##  5                 Braveheart
##  6                About a Boy
##  7 10 Things I Hate About You
##  8            Man on the Moon
##  9           The Last Samurai
## 10                  25th Hour
## # ... with 40 more rows
coldG <- head(find_film(0, gnr, wrd1,wrd2,wrd3,wrd4,wrd5),n=1)

Режиссеры

# creating WIDE format
data2$value = 1
data2w = spread(data2, director_name, value, fill = 0)

Считаем матрицу схожести фильмов:

rownames(data2w) = data2w$movie_id
## Warning: Setting row names on a tibble is deprecated.
data2w %<>% dplyr::select(-movie_id)
sim2 = lsa::cosine(t(as.matrix(data2w)))

# удаляем единицы в диагональных значениях 
diag(sim2) = 0

Функция по режиссерам:

# итоговый вариант; nof = 5 - количество рекомендаций)
find_film2 = function(userId, director, nof = 100){
  m = marks_3 %>% filter(user_id == userId) %>% filter(mark %in% max(mark)) %>% filter(movie_id %in% data$movie_id)                
  if (nrow(m) > 0){
    
    mostSimilar = head(sort(sim2[,as.character(m$movie_id)], decreasing = T), n = 100)
    a = which(sim2[,as.character(m$movie_id)] %in% mostSimilar, arr.ind = TRUE)
    rows = a %% dim(sim2)[1]
    result = rownames(sim2)[rows]
    data %>% filter(movie_id %in% result) %>% filter(str_detect(director_name, director)) %>% dplyr::select(title) %>% head(nof, title)
    
    } else {
    
    data %>% filter(str_detect(director_name, director)) %>% top_n(nof, popularity) %>% dplyr::select(title)
      
    }
}

Если пользователь имеет аккаунт в системе: Сделаем рекомендацию для пользователя с userId = 712664, который хочет посмотреть драму, но такую, чтобы её основная тематика не касалсь слов в кавычках

b = sample(top_users$user_id) %>% head(n=1)

recDA <- find_film2(user, drc)
# Убираем фильмы, которые пользователь уже посмотрел
recD <- recDA
recD <- left_join(recD, data, by="title")
recD <- select(recD, title, movie_id)
recD <- left_join(recD, marks_3, by="movie_id")
recD <- filter(recD, recD$user_id==b)

recDA %<>% filter(!title %in% recD$title)

Если пользователь никогда не ставил оценки до этого, пусть в userId пишет “0” (так система сразу перенесёт его ко второй части функции)

find_film2(0, drc)
## # A tibble: 3 x 1
##                     title
##                     <chr>
## 1     The Wedding Planner
## 2 Bringing Down the House
## 3      A Walk to Remember
coldD <- head(find_film2(0, drc),n=1)

Актеры

# creating WIDE format
data3$value = 1
data3w = spread(data3, actor1_name, value, fill = 0)

Считаем матрицу схожести фильмов:

rownames(data3w) = data3w$movie_id
## Warning: Setting row names on a tibble is deprecated.
data3w %<>% dplyr::select(-movie_id)
sim3 = lsa::cosine(t(as.matrix(data3w)))

# удаляем единицы в диагональных значениях 
diag(sim3) = 0

Функция по актерам:

# итоговый вариант; nof = 5 - количество рекомендаций)
find_film3 = function(userId, actor, nof = 250){
  m = marks_3 %>% filter(user_id == userId) %>% filter(mark %in% max(mark)) %>% filter(movie_id %in% data$movie_id)                
  if (nrow(m) > 0){
    
    mostSimilar = head(sort(sim3[,as.character(m$movie_id)], decreasing = T), n = 250)
    a = which(sim3[,as.character(m$movie_id)] %in% mostSimilar, arr.ind = TRUE)
    rows = a %% dim(sim3)[1]
    result = rownames(sim3)[rows]
    data %>% filter(movie_id %in% result) %>% filter(str_detect(actor1_name, actor)) %>%  dplyr::select(title) %>% head(nof, title)
    
    } else {
    
    data %>% filter(str_detect(actor1_name, actor)) %>% top_n(nof, popularity) %>% dplyr::select(title)
      
    }
}

Если пользователь имеет аккаунт в системе: Сделаем рекомендацию для пользователя с userId = 712664, который хочет посмотреть драму, но такую, чтобы её основная тематика не касалсь слов в кавычках

c = sample(top_users$user_id) %>% head(n=1)

recAA <- find_film3(c, act)
# Убираем фильмы, которые пользователь уже посмотрел
recA <- recAA
recA <- left_join(recA, data, by="title")
recA <- select(recA, title, movie_id)
recA <- left_join(recA, marks_3, by="movie_id")
recA <- filter(recA, recA$user_id==c)

recAA %<>% filter(!title %in% recA$title)

Если пользователь никогда не ставил оценки до этого, пусть в userId пишет “0” (так система сразу перенесёт его ко второй части функции)

find_film3(0, act)
## # A tibble: 4 x 1
##                  title
##                  <chr>
## 1                Dogma
## 2       200 Cigarettes
## 3 The Sum of All Fears
## 4                Gigli
coldA <- head(find_film3(0, act),n=1)

Оскар

Данная рекомендательная система работает только с уже существующими юзерами, которые оценивали фильмы - алгоритм смотрит на оцененные юзером фильмы, ищет среди них фильмы-победители/номинанты на Оскар за определённые категории и предлагает фильмы, которые были номинированы на Оскар или побеждали в этих же категориях.

Допустим, пользователь посмотрел несколько фильмов, которые победили/были номинированы на Оскар за лучшие костюмы, тогда мы делаем предплоложение, что этому пользователю нравятся в фильмах именно костюмы и предлагаем ему другие фильмы, которые также победили/были номинированы на Оскар за лучшие костюмы - и так по любой категории фильмов.

# creating WIDE format
data4 = select(data4, -title)
data4w = spread(data4, Award, prize, fill = 0)
data4 = left_join(data4,data0,by="movie_id")


data4 %<>% mutate(prize=ifelse(data4$prize==0,0,1))

Считаем матрицу схожести фильмов:

rownames(data4w) = data4w$movie_id
## Warning: Setting row names on a tibble is deprecated.
data4w %<>% dplyr::select(-movie_id)
sim4 = lsa::cosine(t(as.matrix(data4w)))

# удаляем единицы в диагональных значениях 
diag(sim4) = 0

Функция по Оскару:

# итоговый вариант; nof = 5 - количество рекомендаций)
data4w$movie_id = as.integer(rownames(data4w))
data4w = left_join(data4w,data0,by="movie_id")

find_film4 = function(userId, prize, nof = 250){
  m = marks_3 %>% filter(user_id == userId) %>% filter(mark %in% max(mark)) %>% filter(movie_id %in% data4$movie_id)                
  if (nrow(m) > 0){
    
    mostSimilar = head(sort(sim4[,as.character(m$movie_id)], decreasing = T), n = 250)
    a = which(sim4[,as.character(m$movie_id)] %in% mostSimilar, arr.ind = TRUE)
    rows = a %% dim(sim4)[1]
    result = rownames(sim4)[rows]
    data4Oscar %>% filter(movie_id %in% result) %>% filter(str_detect(Award, prize)) %>%  dplyr::select(title) %>% head(nof, title)
    
    } else {
    
    data4Oscar %>% filter(str_detect(Award, prize)) %>% top_n(nof, popularity) %>% dplyr::select(title)
      
    }
}

Если пользователь имеет аккаунт в системе: Сделаем рекомендацию для пользователя с userId = 712664, который хочет посмотреть драму, но такую, чтобы её основная тематика не касалсь слов в кавычках

d = sample(top_users$user_id) %>% head(n=1)

recOA <- find_film4(d, osc)
# Убираем фильмы, которые пользователь уже посмотрел
recO <- recOA
recO <- left_join(recO, data, by="title")
recO <- select(recO, title, movie_id)
recO <- left_join(recO, marks_3, by="movie_id")
recO <- filter(recO, recO$user_id==d)

recOA %<>% filter(!title %in% recA$title)

Если пользователь никогда не ставил оценки до этого, пусть в userId пишет “0” (так система сразу перенесёт его ко второй части функции)

find_film4(0, osc)
## # A tibble: 23 x 1
##                 title
##                 <chr>
##  1               Jaws
##  2          The Piano
##  3    Midnight Cowboy
##  4         Braveheart
##  5     The Full Monty
##  6             Gandhi
##  7    Erin Brockovich
##  8 A Passage to India
##  9     Apocalypse Now
## 10 Lawrence of Arabia
## # ... with 13 more rows
coldO <- head(find_film4(0, osc),n=1)

Коллаборативная система

markss=marks_3%>%group_by(user_id)%>%count() 
table(markss$n) 
## 
##     1     2     3     4     5     6     7     8     9    10    11    12 
## 17516 19609 21076 21106 20240 19449 18017 16439 14683 13325 11992 10915 
##    13    14    15    16    17    18    19    20    21    22    23    24 
##  9908  9073  8656  7952  7518  6958  6448  6240  6155  5740  5409  5190 
##    25    26    27    28    29    30    31    32    33    34    35    36 
##  5063  4690  4698  4486  4359  4127  3956  3852  3808  3698  3671  3424 
##    37    38    39    40    41    42    43    44    45    46    47    48 
##  3297  3269  3158  3017  2882  2871  2736  2620  2640  2408  2492  2362 
##    49    50    51    52    53    54    55    56    57    58    59    60 
##  2347  2192  2209  2053  2020  1987  1934  1792  1841  1834  1774  1616 
##    61    62    63    64    65    66    67    68    69    70    71    72 
##  1695  1619  1562  1495  1547  1493  1424  1392  1368  1306  1298  1251 
##    73    74    75    76    77    78    79    80    81    82    83    84 
##  1270  1257  1141  1204  1071  1081  1098  1098  1048   974   925   919 
##    85    86    87    88    89    90    91    92    93    94    95    96 
##   950   901   918   872   874   837   854   806   805   779   688   758 
##    97    98    99   100   101   102   103   104   105   106   107   108 
##   731   697   637   688   614   570   604   563   569   562   562   502 
##   109   110   111   112   113   114   115   116   117   118   119   120 
##   549   540   527   504   522   429   449   429   419   423   390   438 
##   121   122   123   124   125   126   127   128   129   130   131   132 
##   422   379   388   369   342   363   361   328   342   301   339   303 
##   133   134   135   136   137   138   139   140   141   142   143   144 
##   321   281   292   281   272   272   241   249   258   234   273   239 
##   145   146   147   148   149   150   151   152   153   154   155   156 
##   232   209   209   213   193   202   200   208   192   198   183   184 
##   157   158   159   160   161   162   163   164   165   166   167   168 
##   173   165   164   169   145   136   128   145   140   129   134   133 
##   169   170   171   172   173   174   175   176   177   178   179   180 
##   142   131   114   117   134   109    95    88   105   107   111   105 
##   181   182   183   184   185   186   187   188   189   190   191   192 
##   100    86    89    90    67    87    93    84    81    86    62    77 
##   193   194   195   196   197   198   199   200   201   202   203   204 
##    76    58    80    58    62    74    66    49    58    45    71    45 
##   205   206   207   208   209   210   211   212   213   214   215   216 
##    54    67    44    32    57    43    29    39    35    35    37    28 
##   217   218   219   220   221   222   223   224   225   226   227   228 
##    30    30    41    37    23    26    33    33    30    30    33    32 
##   229   230   231   232   233   234   235   236   237   238   239   240 
##    32    20    24    31    23    26    36    30    14    23    23    20 
##   241   242   243   244   245   246   247   248   249   250   251   252 
##    22    11    15    15    16    14    16     8    16    12    15    11 
##   253   254   255   256   257   258   259   260   261   262   263   264 
##    15    15    15    18     9     8    12     9    18    12     9     9 
##   265   266   267   268   269   270   271   272   273   274   275   276 
##    13    11    10     8     8    10     8     6     8     8    15     6 
##   277   278   279   280   281   282   283   284   285   286   287   288 
##    14     7    10    11    10     5     4     4     5     6     9     8 
##   289   290   291   292   293   295   296   297   299   300   301   302 
##     3     6     2     4     9     5     6     8     3     2     6     1 
##   303   304   305   306   307   308   309   310   311   312   313   314 
##     4     4     4     1     3     1     1     2     2     1     2     3 
##   315   316   317   320   321   322   323   324   325   326   327   329 
##     4     2     1     3     3     4     1     2     1     3     1     2 
##   330   332   333   334   335   336   337   340   341   342   344   345 
##     2     1     1     2     2     1     1     1     1     3     1     3 
##   348   350   356   357   359   360   364   365   367   368   375   376 
##     1     1     1     1     1     1     2     1     1     2     1     1 
##   378   379   386   389   397   401   404   413   414   436   447   452 
##     1     1     1     1     1     1     1     2     1     1     1     1 
##   458   462   488   489   495   499 
##     1     1     1     1     1     1
marksss=markss%>%filter(n>100)%>%select(-n) 
markssss=left_join(x=marksss,y=marks_3,by="user_id")
mn= left_join(x=markssss,y=movies,by="movie_id") 

Сохраним только оценки пользователей и фильмы

rates = select(mn, user_id, movie_id, mark) 
 
my_review = data.frame(user_id = c(1000000,1000000,1000000,1000000,1000000, 1000000), movie_id = c(2470, 3938, 5430, 14209,1073, 8644), mark = c(4, 5, 3, 5, 3, 4) ) 
 
rates = bind_rows(rates, my_review) 

Преобразуем к таблице в “широком” формате

library(tidyr) 
rates = spread(rates, key = movie_id, value = mark) 

Для дальнейшей работы в данных должны остаться только оценки, поэтому переведем сначала пользователей в имена строк

rownames(rates) = rates$user_id 
## Warning: Setting row names on a tibble is deprecated.
rates = dplyr::select(rates, -user_id) 
## Adding missing grouping variables: `user_id`
library(recommenderlab) 
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## The following object is masked from 'package:tidyr':
## 
##     expand
## Loading required package: arules
## 
## Attaching package: 'arules'
## The following object is masked from 'package:dplyr':
## 
##     recode
## The following objects are masked from 'package:base':
## 
##     abbreviate, write
## Loading required package: proxy
## 
## Attaching package: 'proxy'
## The following object is masked from 'package:Matrix':
## 
##     as.matrix
## The following objects are masked from 'package:stats':
## 
##     as.dist, dist
## The following object is masked from 'package:base':
## 
##     as.matrix
## Loading required package: registry
rates = as.matrix(rates) 
r = as(rates, "realRatingMatrix") 
r 
## 26768 x 501 rating matrix of class 'realRatingMatrix' with 3791425 ratings.
head(rowMeans(r)) 
##        7       79      134      199      481      769 
## 3.899083 3.908397 5.689394 5.672897 8.764151 8.976562
head(colMeans(r)) 
##      user_id            3           45          148          167 
## 1.324411e+06 3.435644e+00 2.958914e+00 3.215813e+00 3.824919e+00 
##          175 
## 3.986182e+00

Похожесть фильмов и пользователей.

Рассмотрим похожесть первых 15 пользователей (чем ближе к нулю, тем больше схожи пользователи. 1 - полная несхожесть):

similarity_users15 <- similarity(r[1:15, ], method = "cosine", which = "user") 
as.matrix(similarity_users15) 
##              7        79       134       199       481       769      1310
## 7    0.0000000 0.5031747 0.4638638 0.3615757 0.3129351 0.2558470 0.2456068
## 79   0.5031747 0.0000000 0.9942512 0.9826012 0.9704653 0.9669163 0.9596618
## 134  0.4638638 0.9942512 0.0000000 0.9909353 0.9799733 0.9703067 0.9701322
## 199  0.3615757 0.9826012 0.9909353 0.0000000 0.9970274 0.9926225 0.9923791
## 481  0.3129351 0.9704653 0.9799733 0.9970274 0.0000000 0.9991534 0.9989589
## 769  0.2558470 0.9669163 0.9703067 0.9926225 0.9991534 0.0000000 0.9999365
## 1310 0.2456068 0.9596618 0.9701322 0.9923791 0.9989589 0.9999365 0.0000000
## 1333 0.2056341 0.9289050 0.9514750 0.9869486 0.9979344 0.9997273 0.9999397
## 1442 0.2443682 0.9476219 0.9639546 0.9925739 0.9987121 0.9999266 0.9999741
## 1457 0.2277609 0.9506302 0.9670147 0.9911629 0.9987234 0.9998503 0.9999752
## 1500 0.2325164 0.9489738 0.9665103 0.9902719 0.9986739 0.9998694 0.9999786
## 1527 0.2615272 0.9580362 0.9655750 0.9912500 0.9986063 0.9998454 0.9999798
## 1897 0.2560250 0.9617354 0.9678940 0.9931153 0.9989072 0.9998740 0.9999720
## 1918 0.2413101 0.9580342 0.9671351 0.9918959 0.9985564 0.9998164 0.9999475
## 2000 0.2395212 0.9640998 0.9652337 0.9907977 0.9986467 0.9998095 0.9999572
##           1333      1442      1457      1500      1527      1897      1918
## 7    0.2056341 0.2443682 0.2277609 0.2325164 0.2615272 0.2560250 0.2413101
## 79   0.9289050 0.9476219 0.9506302 0.9489738 0.9580362 0.9617354 0.9580342
## 134  0.9514750 0.9639546 0.9670147 0.9665103 0.9655750 0.9678940 0.9671351
## 199  0.9869486 0.9925739 0.9911629 0.9902719 0.9912500 0.9931153 0.9918959
## 481  0.9979344 0.9987121 0.9987234 0.9986739 0.9986063 0.9989072 0.9985564
## 769  0.9997273 0.9999266 0.9998503 0.9998694 0.9998454 0.9998740 0.9998164
## 1310 0.9999397 0.9999741 0.9999752 0.9999786 0.9999798 0.9999720 0.9999475
## 1333 0.0000000 0.9999037 0.9999642 0.9999523 0.9999521 0.9999754 0.9999573
## 1442 0.9999037 0.0000000 0.9999639 0.9999572 0.9999730 0.9999540 0.9999337
## 1457 0.9999642 0.9999639 0.0000000 0.9999799 0.9999797 0.9999830 0.9999641
## 1500 0.9999523 0.9999572 0.9999799 0.0000000 0.9999757 0.9999821 0.9999660
## 1527 0.9999521 0.9999730 0.9999797 0.9999757 0.0000000 0.9999834 0.9999740
## 1897 0.9999754 0.9999540 0.9999830 0.9999821 0.9999834 0.0000000 0.9999816
## 1918 0.9999573 0.9999337 0.9999641 0.9999660 0.9999740 0.9999816 0.0000000
## 2000 0.9999648 0.9999467 0.9999762 0.9999754 0.9999853 0.9999848 0.9999888
##           2000
## 7    0.2395212
## 79   0.9640998
## 134  0.9652337
## 199  0.9907977
## 481  0.9986467
## 769  0.9998095
## 1310 0.9999572
## 1333 0.9999648
## 1442 0.9999467
## 1457 0.9999762
## 1500 0.9999754
## 1527 0.9999853
## 1897 0.9999848
## 1918 0.9999888
## 2000 0.0000000
image(as.matrix(similarity_users15), main = "User similarity") 

Схожесть фильмов:

similarity_items10 <- similarity(r[ ,1:10 ], method = "cosine", which = "items") 
as.matrix(similarity_items10) 
##           user_id         3        45       148       167       175
## user_id 0.0000000 0.8308339 0.8338002 0.8240311 0.8361083 0.8406427
## 3       0.8308339 0.0000000 0.9340915 0.8613332 0.9611704 0.9405935
## 45      0.8338002 0.9340915 0.0000000 0.9339134 0.9354400 0.9207791
## 148     0.8240311 0.8613332 0.9339134 0.0000000 0.9101498 0.9104461
## 167     0.8361083 0.9611704 0.9354400 0.9101498 0.0000000 0.9397583
## 175     0.8406427 0.9405935 0.9207791 0.9104461 0.9397583 0.0000000
## 181     0.8158412 0.9129934 0.9183559 0.9010467 0.9258057 0.9326005
## 213     0.8351627 0.9534264 0.9641488 0.9128488 0.9571725 0.9466281
## 216     0.8345324 0.9198758 0.9249114 0.9423931 0.9101503 0.9339023
## 329     0.8277691 0.9141463 0.9258719 0.9121601 0.9275266 0.9449366
##               181       213       216       329
## user_id 0.8158412 0.8351627 0.8345324 0.8277691
## 3       0.9129934 0.9534264 0.9198758 0.9141463
## 45      0.9183559 0.9641488 0.9249114 0.9258719
## 148     0.9010467 0.9128488 0.9423931 0.9121601
## 167     0.9258057 0.9571725 0.9101503 0.9275266
## 175     0.9326005 0.9466281 0.9339023 0.9449366
## 181     0.0000000 0.9272514 0.9362987 0.9185125
## 213     0.9272514 0.0000000 0.9332700 0.9228805
## 216     0.9362987 0.9332700 0.0000000 0.9313528
## 329     0.9185125 0.9228805 0.9313528 0.0000000
image(as.matrix(similarity_items10), main = "Item similarity") 

Чем темнее ячейка, тем больше схожесть.

Подготовка данных:

Количество оценок у фильма:

ggplot(data = data.frame(filmRate=colCounts(r))) + geom_histogram(aes(x=filmRate)) 
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Количество оценок, поставленных одним пользователем:

ggplot(data = data.frame(userRate=rowCounts(r))) + geom_histogram(aes(x=userRate)) 
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

ratings_movies <- r[rowCounts(r) > 100, colCounts(r) > 40] 
ratings_movies 
## 26767 x 500 rating matrix of class 'realRatingMatrix' with 3791378 ratings.

Метод коллаборативной фильтрации:

Разделим данные на тестовую и обучающую выборки. На обучающей построим модель, для пользователей из тестовой будем рекомендовать фильмы.

set.seed(100) 
test_ind <- sample(1:nrow(ratings_movies), size = nrow(ratings_movies)*0.2) 
recc_data_train <- ratings_movies[-test_ind, ] 
recc_data_test <- ratings_movies[test_ind, ] 

IBCF (основан на схожести фильмов) -вычислить похожесть всех пар фильмов -для каждого фильма найти k наиболее похожих -для каждого пользователя определить фильмы, наиболее близкие к тем, которые он оценил

recc_model <- Recommender(data = recc_data_train, method = "IBCF", parameter = list(k = 30)) 
recc_model 
## Recommender of type 'IBCF' for 'realRatingMatrix' 
## learned using 21414 users.

Матрица схожести:

model_details <- getModel(recc_model) 
model_details$description 
## [1] "IBCF: Reduced similarity matrix"
model_details$sim[25:30, 40:55] 
## 6 x 16 sparse Matrix of class "dgCMatrix"
##    [[ suppressing 16 column names '1336', '1367', '1394' ... ]]
##                                    
## 746 . . . . . . . . . . . . . . . .
## 758 . . . . . . . . . . . . . . . .
## 798 . . . . . . . . . . . . . . . .
## 811 1 . . 1 . . . . . . . . 1 . . .
## 829 . . . . . . . . . . . . . . . .
## 962 . . . . . . . . . . . . . . . .
recc_predicted <- predict(object = recc_model, newdata = recc_data_test, n = 5) 
recc_predicted 
## Recommendations as 'topNList' with n = 5 for 5353 users.

Теперь наша рекомендательная система будет рекомендовать пользователю 5 фильмов.

str(recc_predicted) 
## Formal class 'topNList' [package "recommenderlab"] with 4 slots
##   ..@ items     :List of 5353
##   .. ..$ 818736 : int [1:5] 336 430 373 437 261
##   .. ..$ 693353 : int [1:5] 345 416 281 325 148
##   .. ..$ 1454357: int [1:5] 454 45 97 147 307
##   .. ..$ 153500 : int [1:5] 38 416 494 47 226
##   .. ..$ 1239121: int [1:5] 322 287 155 441 31
##   .. ..$ 1279398: int [1:5] 84 310 54 301 170
##   .. ..$ 2145206: int [1:5] 322 5 301 376 437
##   .. ..$ 978881 : int [1:5] 498 226 278 176 325
##   .. ..$ 1439261: int [1:5] 371 32 281 97 301
##   .. ..$ 460526 : int [1:5] 112 251 299 385 437
##   .. ..$ 1644255: int [1:5] 97 186 326 437 230
##   .. ..$ 2339841: int [1:5] 328 191 126 420 259
##   .. ..$ 750327 : int [1:5] 50 187 352 494 325
##   .. ..$ 1056819: int [1:5] 14 45 70 124 180
##   .. ..$ 2014656: int [1:5] 5 20 81 84 228
##   .. ..$ 1761324: int [1:5] 14 437 493 91 97
##   .. ..$ 549416 : int [1:5] 416 239 435 393 264
##   .. ..$ 944189 : int [1:5] 310 326 385 493 51
##   .. ..$ 950078 : int [1:5] 139 199 345 2 13
##   .. ..$ 1818137: int [1:5] 97 416 22 393 343
##   .. ..$ 1412898: int [1:5] 219 14 279 490 224
##   .. ..$ 1874187: int [1:5] 226 168 243 309 494
##   .. ..$ 1418569: int [1:5] 326 421 2 416 345
##   .. ..$ 1976734: int [1:5] 435 449 497 299 94
##   .. ..$ 1114617: int [1:5] 41 50 156 344 454
##   .. ..$ 464621 : int [1:5] 84 90 354 437 322
##   .. ..$ 2035310: int [1:5] 7 123 2 81 216
##   .. ..$ 2338153: int [1:5] 156 480 246 434 155
##   .. ..$ 1444640: int [1:5] 402 310 6 10 146
##   .. ..$ 742799 : int [1:5] 118 214 499 226 297
##   .. ..$ 1290120: int [1:5] 38 332 491 479 232
##   .. ..$ 2459573: int [1:5] 50 187 236 190 121
##   .. ..$ 922922 : int [1:5] 97 354 272 195 2
##   .. ..$ 2524669: int [1:5] 27 472 487 45 176
##   .. ..$ 1829014: int [1:5] 81 412 430 470 33
##   .. ..$ 2356471: int [1:5] 118 180 214 344 90
##   .. ..$ 486399 : int [1:5] 59 299 5 278 204
##   .. ..$ 1654132: int [1:5] 344 272 148 281 34
##   .. ..$ 2618955: int [1:5] 325 195 437 443 354
##   .. ..$ 356103 : int [1:5] 258 310 487 176 2
##   .. ..$ 875273 : int [1:5] 158 272 362 185 5
##   .. ..$ 2288907: int [1:5] 354 180 138 470 243
##   .. ..$ 2051379: int [1:5] 421 435 77 313 487
##   .. ..$ 2185062: int [1:5] 2 494 41 266 230
##   .. ..$ 1584352: int [1:5] 97 421 402 321 454
##   .. ..$ 1295424: int [1:5] 344 254 287 468 371
##   .. ..$ 2058312: int [1:5] 199 272 494 38 39
##   .. ..$ 2341509: int [1:5] 266 487 354 2 230
##   .. ..$ 557167 : int [1:5] 416 138 176 336 443
##   .. ..$ 815165 : int [1:5] 243 322 272 470 176
##   .. ..$ 874732 : int [1:5] 50 97 266 272 454
##   .. ..$ 531396 : int [1:5] 112 325 345 245 50
##   .. ..$ 633253 : int [1:5] 124 393 243 18 264
##   .. ..$ 735078 : int [1:5] 228 379 412 371 279
##   .. ..$ 1553270: int [1:5] 494 322 487 301 376
##   .. ..$ 679947 : int [1:5] 336 322 380 493 54
##   .. ..$ 336413 : int [1:5] 74 272 176 148 97
##   .. ..$ 617786 : int [1:5] 91 322 214 443 180
##   .. ..$ 1568758: int [1:5] 148 187 243 87 138
##   .. ..$ 567198 : int [1:5] 321 209 98 309 158
##   .. ..$ 1225081: int [1:5] 266 345 344 41 375
##   .. ..$ 1698123: int [1:5] 385 251 267 375 70
##   .. ..$ 2538880: int [1:5] 281 336 5 487 224
##   .. ..$ 1777917: int [1:5] 487 354 443 430 336
##   .. ..$ 1174173: int [1:5] 325 47 195 437 336
##   .. ..$ 943314 : int [1:5] 344 70 243 51 325
##   .. ..$ 1203374: int [1:5] 247 262 357 14 380
##   .. ..$ 1174779: int [1:5] 345 416 437 281 354
##   .. ..$ 657364 : int [1:5] 416 375 91 261 412
##   .. ..$ 1824444: int [1:5] 354 24 357 409 487
##   .. ..$ 1092677: int [1:5] 80 165 274 153 92
##   .. ..$ 867947 : int [1:5] 171 272 226 313 188
##   .. ..$ 1502539: int [1:5] 2 23 266 136 379
##   .. ..$ 2556129: int [1:5] 390 99 260 201 33
##   .. ..$ 1737824: int [1:5] 112 357 239 366 249
##   .. ..$ 1638551: int [1:5] 66 77 139 385 156
##   .. ..$ 2260472: int [1:5] 197 325 494 437 261
##   .. ..$ 2042756: int [1:5] 286 180 230 393 195
##   .. ..$ 2203182: int [1:5] 149 220 343 101 390
##   .. ..$ 252054 : int [1:5] 288 118 170 345 310
##   .. ..$ 1213065: int [1:5] 322 326 213 81 51
##   .. ..$ 1572525: int [1:5] 77 33 213 247 345
##   .. ..$ 2430356: int [1:5] 38 251 322 417 294
##   .. ..$ 2596404: int [1:5] 322 487 334 98 437
##   .. ..$ 104237 : int [1:5] 232 381 408 18 64
##   .. ..$ 1516350: int [1:5] 301 310 20 373 111
##   .. ..$ 1930074: int [1:5] 228 307 393 138 8
##   .. ..$ 667438 : int [1:5] 402 5 59 158 216
##   .. ..$ 795665 : int [1:5] 33 79 371 376 281
##   .. ..$ 1930443: int [1:5] 344 468 345 279 146
##   .. ..$ 2397057: int [1:5] 345 32 371 171 258
##   .. ..$ 561700 : int [1:5] 224 443 24 345 416
##   .. ..$ 2643082: int [1:5] 50 123 129 493 404
##   .. ..$ 1181609: int [1:5] 219 31 480 236 287
##   .. ..$ 2396038: int [1:5] 195 261 354 325 437
##   .. ..$ 1027371: int [1:5] 322 146 115 236 400
##   .. ..$ 1360897: int [1:5] 379 156 416 310 50
##   .. ..$ 341468 : int [1:5] 281 322 416 149 245
##   .. ..$ 82577  : int [1:5] 79 156 180 138 228
##   .. .. [list output truncated]
##   ..@ ratings   :List of 5353
##   .. ..$ 818736 : num [1:5] 3.87 3.83 3.73 3.69 3.64
##   .. ..$ 693353 : num [1:5] 5 4.67 4.63 4.56 4.55
##   .. ..$ 1454357: num [1:5] 4.6 4.58 4.57 4.5 4.44
##   .. ..$ 153500 : num [1:5] 4 4 4 3.93 3.89
##   .. ..$ 1239121: num [1:5] 3.8 3.55 3.5 3.4 3.38
##   .. ..$ 1279398: num [1:5] 4.5 4.38 4.19 4.14 4.07
##   .. ..$ 2145206: num [1:5] 4.2 4.18 4.18 4.16 4.15
##   .. ..$ 978881 : num [1:5] 4.29 4.29 4.27 4.25 4.22
##   .. ..$ 1439261: num [1:5] 4.38 4.37 4.33 4.33 4.25
##   .. ..$ 460526 : num [1:5] 5 5 5 5 4.78
##   .. ..$ 1644255: num [1:5] 5 4.33 4.27 4.25 4.2
##   .. ..$ 2339841: num [1:5] 4 3.86 3.75 3.75 3.67
##   .. ..$ 750327 : num [1:5] 4 4 4 4 3.67
##   .. ..$ 1056819: num [1:5] 5 5 5 5 5
##   .. ..$ 2014656: num [1:5] 5 5 5 5 5
##   .. ..$ 1761324: num [1:5] 4.79 4.71 4.69 4.68 4.67
##   .. ..$ 549416 : num [1:5] 5 4.11 4 4 4
##   .. ..$ 944189 : num [1:5] 4.5 4.42 4.4 4.38 4.37
##   .. ..$ 950078 : num [1:5] 5 5 5 5 5
##   .. ..$ 1818137: num [1:5] 5 4.5 4.5 4.5 4.21
##   .. ..$ 1412898: num [1:5] 3.5 3.5 3.5 3.5 3.5
##   .. ..$ 1874187: num [1:5] 4 4 4 4 4
##   .. ..$ 1418569: num [1:5] 4.27 4.25 4.25 4.25 4.2
##   .. ..$ 1976734: num [1:5] 5 5 5 4.5 4.5
##   .. ..$ 1114617: num [1:5] 4 4 4 4 4
##   .. ..$ 464621 : num [1:5] 4.33 4.07 4 4 4
##   .. ..$ 2035310: num [1:5] 5 4.75 4.71 4.71 4.67
##   .. ..$ 2338153: num [1:5] 5 4.17 4.14 4.12 4.07
##   .. ..$ 1444640: num [1:5] 4.5 4.14 4.09 4.05 4
##   .. ..$ 742799 : num [1:5] 5 4.5 4.4 4.17 4.17
##   .. ..$ 1290120: num [1:5] 5 4.78 4.75 4.58 4.56
##   .. ..$ 2459573: num [1:5] 4 4 4 3.89 3.89
##   .. ..$ 922922 : num [1:5] 4.58 4.56 4.55 4.5 4.44
##   .. ..$ 2524669: num [1:5] 4.32 4.26 4.17 4.13 4.12
##   .. ..$ 1829014: num [1:5] 5 5 4.35 4.33 4.33
##   .. ..$ 2356471: num [1:5] 5 5 5 5 5
##   .. ..$ 486399 : num [1:5] 5 4.5 4.4 4.25 4.14
##   .. ..$ 1654132: num [1:5] 5 4.75 4.71 4.57 4.5
##   .. ..$ 2618955: num [1:5] 4.5 4.37 4.37 4.37 4.37
##   .. ..$ 356103 : num [1:5] 5 4.44 4.4 4.2 4.17
##   .. ..$ 875273 : num [1:5] 5 5 4.67 4.67 4.67
##   .. ..$ 2288907: num [1:5] 5 4.67 4.5 4.5 4.5
##   .. ..$ 2051379: num [1:5] 5 5 4.5 4.31 4.25
##   .. ..$ 2185062: num [1:5] 5 5 5 5 4.75
##   .. ..$ 1584352: num [1:5] 5 4.5 4.5 4.12 4
##   .. ..$ 1295424: num [1:5] 4 3.64 3.63 3.61 3.6
##   .. ..$ 2058312: num [1:5] 5 5 5 5 5
##   .. ..$ 2341509: num [1:5] 3.79 3.77 3.73 3.73 3.71
##   .. ..$ 557167 : num [1:5] 5 4.75 4.75 4.62 4.6
##   .. ..$ 815165 : num [1:5] 5 5 4.83 4.78 4.75
##   .. ..$ 874732 : num [1:5] 5 5 5 5 5
##   .. ..$ 531396 : num [1:5] 5 4.67 4.67 4.5 4.5
##   .. ..$ 633253 : num [1:5] 4.5 4.5 4.33 4.33 4.25
##   .. ..$ 735078 : num [1:5] 4 4 4 3.8 3.74
##   .. ..$ 1553270: num [1:5] 5 4.75 4.71 4.5 4.5
##   .. ..$ 679947 : num [1:5] 4.16 4.14 4.11 4.1 4.09
##   .. ..$ 336413 : num [1:5] 4 3.92 3.83 3.82 3.8
##   .. ..$ 617786 : num [1:5] 4.5 4.33 4.33 4.33 4.33
##   .. ..$ 1568758: num [1:5] 5 5 5 5 5
##   .. ..$ 567198 : num [1:5] 4 3.67 3.5 3.5 3.4
##   .. ..$ 1225081: num [1:5] 5 5 4.5 4 4
##   .. ..$ 1698123: num [1:5] 5 4.75 4.75 4.7 4.67
##   .. ..$ 2538880: num [1:5] 4.83 4.72 4.71 4.56 4.55
##   .. ..$ 1777917: num [1:5] 5 4.38 4.33 4.25 4.21
##   .. ..$ 1174173: num [1:5] 4.57 4.53 4.5 4.5 4.5
##   .. ..$ 943314 : num [1:5] 5 4.5 4.38 4.33 4.33
##   .. ..$ 1203374: num [1:5] 4.2 4.17 4.06 4 4
##   .. ..$ 1174779: num [1:5] 5 4.67 4.5 4.4 4.38
##   .. ..$ 657364 : num [1:5] 5 4.4 4.38 4.27 4.25
##   .. ..$ 1824444: num [1:5] 4.17 4.13 4.12 4 4
##   .. ..$ 1092677: num [1:5] 5 4.79 4.75 4.73 4.71
##   .. ..$ 867947 : num [1:5] 4.53 4.5 4.5 4.43 4.39
##   .. ..$ 1502539: num [1:5] 3.92 3.92 3.91 3.89 3.87
##   .. ..$ 2556129: num [1:5] 4.29 4.15 4.07 4 4
##   .. ..$ 1737824: num [1:5] 5 4.75 4.7 4.63 4.6
##   .. ..$ 1638551: num [1:5] 5 5 5 5 5
##   .. ..$ 2260472: num [1:5] 5 5 5 4.9 4.89
##   .. ..$ 2042756: num [1:5] 5 4.5 4.25 4.2 4.2
##   .. ..$ 2203182: num [1:5] 4.28 4.27 4.25 4.2 4.2
##   .. ..$ 252054 : num [1:5] 4.25 4.2 4.18 4.11 4.1
##   .. ..$ 1213065: num [1:5] 5 4.83 4.75 4.71 4.64
##   .. ..$ 1572525: num [1:5] 5 5 5 5 5
##   .. ..$ 2430356: num [1:5] 5 5 5 5 4.75
##   .. ..$ 2596404: num [1:5] 4.33 4.33 4.33 4.33 4.25
##   .. ..$ 104237 : num [1:5] 5 5 5 5 5
##   .. ..$ 1516350: num [1:5] 4 4 3.74 3.66 3.62
##   .. ..$ 1930074: num [1:5] 4 4 4 4 4
##   .. ..$ 667438 : num [1:5] 5 5 5 5 5
##   .. ..$ 795665 : num [1:5] 4.25 4.2 4.08 4.08 4
##   .. ..$ 1930443: num [1:5] 5 4.25 4.25 4.21 4.2
##   .. ..$ 2397057: num [1:5] 5 4.67 4.33 4.31 4
##   .. ..$ 561700 : num [1:5] 4.08 4.08 4 4 4
##   .. ..$ 2643082: num [1:5] 5 5 4.67 4.5 4.5
##   .. ..$ 1181609: num [1:5] 4.27 4.19 4.18 4.13 4.12
##   .. ..$ 2396038: num [1:5] 4.6 4.5 4.5 4.5 4.5
##   .. ..$ 1027371: num [1:5] 5 4.38 4.33 4.25 4.25
##   .. ..$ 1360897: num [1:5] 5 5 5 4.67 4.67
##   .. ..$ 341468 : num [1:5] 4 4 4 3.83 3.8
##   .. ..$ 82577  : num [1:5] 5 5 5 5 5
##   .. .. [list output truncated]
##   ..@ itemLabels: chr [1:500] "user_id" "3" "45" "148" ...
##   ..@ n         : int 5

Рекомендации для пользователя c user_id= 1360897:

recc_user_1 <- recc_predicted@items[["1360897"]] 
movies_user_1 <- recc_predicted@itemLabels[recc_user_1]#вытащим id фильма 
names_movies_user_1 <- mn$title[match(movies_user_1, mn$movie_id)]#посмотрим на названия фильмов 
names_movies_user_1 
## [1] "Tumbleweeds"            "Major Dundee"          
## [3] "The Work and the Glory" "Oldboy"                
## [5] "Manito"

А теперь попробуем метод UBCF (основан на схожести пользователей) и посмотрим, что в этот раз нам порекомендует системадля десятого пользователя:

recc_model_ubcf <- Recommender(data = recc_data_train, method = "UBCF",parameter = list(nn = 
25)) 
recc_model_ubcf 
## Recommender of type 'UBCF' for 'realRatingMatrix' 
## learned using 21414 users.
#recc_predicted_ubcf <- predict(object = recc_model_ubcf, newdata = recc_data_test, n = 6) 
#recc_predicted_ubcf 
#recc_user_12 <- recc_predicted_ubcf@items[["1360897"]] 
#movies_user_12 <- recc_predicted_ubcf@itemLabels[recc_user_12] 
#names_movies_user_12 <- mn$title[match(movies_user_12, mn$movie_id)] 
#names_movies_user_12 
#recc_model <- Recommender(data = recc_data_train, method = "IBCF", parameter = list(k = 30)) 
#recc_model 
#recc_predicted <- predict(object = recc_model, newdata = recc_data_test, n = 5) 
#recc_predicted 
#допюдатасет:
mnmean=mn%>%group_by(movie_id)%>%summarize(marks=mean(mark,na.rm=T)) 
new=inner_join(mnmean,movies) 
## Joining, by = "movie_id"
newnewnew=new%>%dplyr::select(movie_id,title,popularity,marks) 
find_filmColl=function(user_id, n=6){ 
recc_user_n <- recc_predicted@items[[user_id]] 
if (length(recc_user_n)>0){movies_user_n <- recc_predicted@itemLabels[recc_user_n] 
names_movies_user_n <- mn$title[match(movies_user_n, mn$movie_id)] 
names_movies_user_n} 
else {newnewnew%>%top_n(6,marks)} 
} 
## [1] "Tumbleweeds"            "Major Dundee"          
## [3] "The Work and the Glory" "Oldboy"                
## [5] "Manito"

Финальная рекомендация

coldF <- as.data.frame(bind_rows(coldG,coldD,coldA,coldO,coll))
## Warning in bind_rows_(x, .id): binding character and factor vector,
## coercing into character vector
filter <- data.frame(c("Genre","Director","Actor","Oscar","Other users"))
names(filter)[1] <- "filters"
coldF <- cbind(coldF,filter)
coldF
##                 title     filters
## 1         Wild Things       Genre
## 2 The Wedding Planner    Director
## 3               Dogma       Actor
## 4                Jaws       Oscar
## 5         Tumbleweeds Other users