Procedimiento
- Identificar y cargar los datos de películas; los datos de las películas vistas por los usuarios y de las características de cada película, este último conjunto de datos es la matriz de ceros y unos que significan las características de cada película.
- Generar la la matriz transpuesta del llenado de las películas de ceros y unos. La transpuesta es para identificar las variables que son cada una de las películas a manera de columnas y que precisamente servirán de base para aplicar la función de cor() correlación y encontrar las relaciones entre las pelóculas.
- Determinar la matriz de correlación de las películas para saber que tanto se relaciona una con otra.
- Establecer los nombres de columnas como id de película y los nombres de registros también como los id de películas con el atributo Idmovie de cada película en la matriz de correlación
- Toda vez que se tiene la matriz de correlación, entonces aplicar el modelo para recomendaciones de películas.
- Aplicar el modelo para recomendar películas.
Modelo par recomendar películas
- Identificar el usuario (persona) que se desea recomendar películas.
- Identificar las película que ha visto éste usuario o persona.
- Determinar un vector con las correlaciones mas fuertes de cada película que ha visto el usuario. Esta operción se hace por medio de un ciclo que va desde la primera hasta la última película vista por el usuario.
- Ordenar el vector de acuerdo a la correlación de mayor a menor y determinr los tres primeras más altas relaciones
- Se podría pensar en tres ALGORITMOS para recomendar películas:
- Opción 1: Aquellas que aparecen con mayor frecuencia en el vector de correlaciones. Opción 2: Aquellas que tienen las relaciones más altas.
- Opción 3. Combinar la opción 1 con la opción 2.
- Finalmente, generar una lista de películas que se recomiendan al usuario o persona.
Las librerías
library(readr)
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
Las peliculas
peliculas <- read.csv("https://raw.githubusercontent.com/rpizarrog/Curso-Titulacion-Data-Science-/master/2019/Datos/catalogo%20de%20peliculas.csv", header = TRUE)
head(peliculas)
## movieId title
## 1 1 Toy Story (1995)
## 2 2 Jumanji (1995)
## 3 3 Grumpier Old Men (1995)
## 4 4 Waiting to Exhale (1995)
## 5 5 Father of the Bride Part II (1995)
## 6 6 Heat (1995)
## genres
## 1 Adventure|Animation|Children|Comedy|Fantasy
## 2 Adventure|Children|Fantasy
## 3 Comedy|Romance
## 4 Comedy|Drama|Romance
## 5 Comedy
## 6 Action|Crime|Thriller
Las películas que un usuario ha visto
peliculasVistas <- read.csv("https://raw.githubusercontent.com/rpizarrog/Curso-Titulacion-Data-Science-/master/2019/Datos/preferencias%20de%20peliculas%20por%20usuarios.csv", header = TRUE)
head(peliculasVistas)
## userId movieId rating
## 1 1 1 4
## 2 1 3 4
## 3 1 6 4
## 4 1 47 5
## 5 1 50 5
## 6 1 70 3
Los valores 0 y 1 para cada película
llenadoPeliculas <- read.csv("https://raw.githubusercontent.com/rpizarrog/Curso-Titulacion-Data-Science-/master/2019/Datos/representacion%20vectorial%20todas%20las%20peliculas.csv", header = TRUE)
llenadoPeliculas <- t(llenadoPeliculas) # Transponer la matriz
head(llenadoPeliculas)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
## movieId 1 2 3 4 5 6 7 8 9 10 11 12
## Action 0 0 0 0 0 1 0 0 1 1 0 0
## Adventure 1 1 0 0 0 0 0 1 0 1 0 0
## Animation 1 0 0 0 0 0 0 0 0 0 0 0
## Children 1 1 0 0 0 0 0 1 0 0 0 0
## Comedy 1 0 1 1 1 0 1 0 0 0 1 1
## [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21] [,22]
## movieId 13 14 15 16 17 18 19 20 21 22
## Action 0 0 1 0 0 0 0 1 0 0
## Adventure 1 0 1 0 0 0 0 0 0 0
## Animation 1 0 0 0 0 0 0 0 0 0
## Children 1 0 0 0 0 0 0 0 0 0
## Comedy 0 0 0 0 0 1 1 1 1 0
## [,23] [,24] [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32]
## movieId 23 24 25 26 27 28 29 30 31 32
## Action 1 0 0 0 0 0 0 0 0 0
## Adventure 0 0 0 0 0 0 1 0 0 0
## Animation 0 0 0 0 0 0 0 0 0 0
## Children 0 0 0 0 1 0 0 0 0 0
## Comedy 0 0 0 0 0 0 0 0 0 0
## [,33] [,34] [,35] [,36] [,37] [,38] [,39] [,40] [,41] [,42]
## movieId 34 36 38 39 40 41 42 43 44 45
## Action 0 0 0 0 0 0 1 0 1 0
## Adventure 0 0 0 0 0 0 0 0 1 0
## Animation 0 0 0 0 0 0 0 0 0 0
## Children 1 0 1 0 0 0 0 0 0 0
## Comedy 0 0 1 1 0 0 0 0 0 1
## [,43] [,44] [,45] [,46] [,47] [,48] [,49] [,50] [,51] [,52]
## movieId 46 47 48 49 50 52 53 54 55 57
## Action 0 0 0 0 0 0 0 0 0 0
## Adventure 0 0 0 0 0 0 1 0 0 0
## Animation 0 0 1 0 0 0 0 0 0 0
## Children 0 0 1 0 0 0 0 1 0 0
## Comedy 0 0 0 0 0 1 0 1 0 0
## [,53] [,54] [,55] [,56] [,57] [,58] [,59] [,60] [,61] [,62]
## movieId 58 60 61 62 63 64 65 66 68 69
## Action 0 0 0 0 0 0 0 1 0 0
## Adventure 0 1 0 0 0 0 0 0 0 0
## Animation 0 0 0 0 0 0 0 0 0 0
## Children 0 1 0 0 0 0 0 0 0 0
## Comedy 1 0 0 0 1 1 1 0 1 1
## [,63] [,64] [,65] [,66] [,67] [,68] [,69] [,70] [,71] [,72]
## movieId 70 71 72 73 74 75 76 77 78 79
## Action 1 1 0 0 0 0 1 0 1 0
## Adventure 0 0 0 0 0 0 0 0 0 0
## Animation 0 0 0 0 0 0 0 0 0 0
## Children 0 0 0 0 0 0 0 0 0 0
## Comedy 1 0 1 0 0 1 0 0 0 0
## [,73] [,74] [,75] [,76] [,77] [,78] [,79] [,80] [,81] [,82]
## movieId 80 81 82 83 85 86 87 88 89 92
## Action 0 0 0 0 0 1 0 0 1 0
## Adventure 0 0 0 0 0 1 0 0 0 0
## Animation 0 0 0 0 0 0 0 0 0 0
## Children 1 0 0 0 0 0 1 0 0 0
## Comedy 0 0 1 0 0 0 1 1 0 0
## [,83] [,84] [,85] [,86] [,87] [,88] [,89] [,90] [,91] [,92]
## movieId 93 94 95 96 97 99 100 101 102 103
## Action 0 0 1 0 0 0 0 0 0 0
## Adventure 0 0 1 0 0 0 0 1 0 0
## Animation 0 0 0 0 0 0 0 0 0 0
## Children 0 0 0 0 0 0 0 0 0 0
## Comedy 1 1 0 1 0 0 0 1 1 0
## [,93] [,94] [,95] [,96] [,97] [,98] [,99] [,100]
## movieId 104 105 106 107 108 110 111 112
## Action 0 0 0 0 0 1 0 1
## Adventure 0 0 0 1 0 0 0 1
## Animation 0 0 0 0 0 0 0 0
## Children 0 0 0 1 0 0 0 0
## Comedy 1 0 1 1 0 0 0 1
La correlación estadística entre cada película
La matriz de correlación la genera son el renglón de movieid [-1,]
correlacionPeliculas <- data.frame(cor(llenadoPeliculas[-1,]))
# head(correlacionPeliculas) # Primeros seis
Poner nombres de columnas y nombres de filas a las matriz de correlación así como el idmovie como nueva columna con los valores de cada película
idpeliculas <- peliculas$movieId
colnames(correlacionPeliculas) <- idpeliculas
rownames(correlacionPeliculas) <- idpeliculas
correlacionPeliculas <- mutate(correlacionPeliculas, movieid = idpeliculas)
head(correlacionPeliculas[,1:10]) # Primeros seis. Ya con columnas nombres y columna movieid y las primeras 10 columnas
## 1 2 3 4 5 6
## 1 1.00000000 0.7125253 0.1528942 0.02159168 0.3829708 -0.3238751
## 2 0.71252530 1.0000000 -0.1815683 -0.23076923 -0.1240347 -0.2307692
## 3 0.15289416 -0.1815683 1.0000000 0.78679579 0.6831301 -0.1815683
## 4 0.02159168 -0.2307692 0.7867958 1.00000000 0.5374838 -0.2307692
## 5 0.38297084 -0.1240347 0.6831301 0.53748385 1.0000000 -0.1240347
## 6 -0.32387514 -0.2307692 -0.1815683 -0.23076923 -0.1240347 1.0000000
## 7 8 9 10
## 1 0.1528942 0.56061191 -0.17407766 0.02159168
## 2 -0.1815683 0.78679579 -0.12403473 0.17948718
## 3 1.0000000 -0.14285714 -0.09759001 -0.18156826
## 4 0.7867958 -0.18156826 -0.12403473 -0.23076923
## 5 0.6831301 -0.09759001 -0.06666667 -0.12403473
## 6 -0.1815683 -0.18156826 0.53748385 0.58974359
tail(correlacionPeliculas[,91:100]) # Últimos seis. Ya con columnas nombres y columna movieid y las últimas columnas
## 102 103 104 105 106 107
## 95 0.68313005 -0.1815683 0.68313005 0.42857143 1.00000000 0.2182179
## 96 0.44721360 -0.2773501 0.44721360 -0.21821789 0.21821789 1.0000000
## 97 -0.06666667 -0.1240347 -0.06666667 -0.09759001 -0.09759001 -0.1490712
## 98 -0.12403473 -0.2307692 -0.12403473 0.30261377 0.30261377 -0.2773501
## 99 -0.12403473 0.1794872 -0.12403473 0.30261377 0.30261377 -0.2773501
## 100 0.44721360 -0.2773501 0.44721360 -0.21821789 0.21821789 0.3333333
## 108 110 111 112
## 95 -0.09759001 0.30261377 0.30261377 0.21821789
## 96 -0.14907120 -0.27735010 -0.27735010 0.33333333
## 97 1.00000000 -0.12403473 -0.12403473 -0.14907120
## 98 -0.12403473 1.00000000 0.17948718 0.09245003
## 99 -0.12403473 0.17948718 1.00000000 0.09245003
## 100 -0.14907120 0.09245003 0.09245003 1.00000000
Cuales películas se le recomienda ver al usuario
Primero, ¿cuáles películas ha visto el usuario ?
usuario <- 38 # Aqu se define cual usuario, del 1 al 610
pelVistaUsuario <- filter(peliculasVistas, userId == usuario)
pelVistaUsuario # Son las peliculas vistas por el usuario
## userId movieId rating
## 1 38 11 5
## 2 38 17 3
## 3 38 21 3
## 4 38 39 3
## 5 38 48 3
## 6 38 50 5
## 7 38 62 3
## 8 38 105 3
## 9 38 110 5
Ahora sacar las correlaciones de cada pelicula vista del usuario
Determinar las mejores 3 correlaciones de cada película
Ordenando las correlaciones
Generando un data frame nuevo con las mejores 3 recomendaciones de cada película que el usuario ha visto
# Generamos un dtaframe vacío
# El datafrme de recomendaciones lo iniciamos vacio
recomendaciones <- data.frame(NA, NA, NA) # Vacio
recomendaciones <- recomendaciones[-1,] # Vacio
colnames(recomendaciones) <- c("Vista", "Recomendada", "Correlación")
recomendaciones # Está vacío el data frame
## [1] Vista Recomendada Correlación
## <0 rows> (or 0-length row.names)
# Un ciclo para recorrer cada película vista por el usaurio
# y generar sus recomendaciones, las tres más altas correlaciones
for (peli in 1:nrow(pelVistaUsuario)) {
# print(pelVistaUsuario[peli,2])
# Se determina las películas recomendadas según las correlaciones más altas.
#Las tres primeras de cada película vista por el usuario
recomendadas <- filter(correlacionPeliculas, movieid == pelVistaUsuario[peli,2])
# Quitar la misma pelicula vista con correlacion igual a 1
recomendadas <- recomendadas[,-which(colnames(recomendadas) == pelVistaUsuario[peli,2])]
recomendadas <- sort(recomendadas, decreasing = TRUE)
recomendadas <- recomendadas[1,3:5] # Las tres mejores
rownames(recomendadas) <- pelVistaUsuario[peli,2] # Conservar el nombre de la fila
# Generamos las recomendaciones de cada película, tres columnas. La primera columna es la película que el usuario ya vió; la segunda columna es la película recomenda con valor de correlación más alto y la tercera columna es el valor de la correlación de la película recomendada.
peliVista <- as.numeric(rep(rownames(recomendadas), 3))
peliVista
peliRecomendada <- as.numeric(colnames(recomendadas[1,1:3]))
peliRecomendada
peliCorrelacionada <- as.numeric(recomendadas[1,1:3])
peliCorrelacionada
pelisRecomendadas <- data.frame(peliVista, peliRecomendada, peliCorrelacionada)
# Poner nombres de columnas al dataframe que se va generando
colnames(pelisRecomendadas) <- c("Vista", "Recomendada", "Correlacion")
recomendaciones <- rbind(recomendaciones, pelisRecomendadas)
}
recomendaciones <- arrange(recomendaciones, desc(Correlacion))
recomendaciones
## Vista Recomendada Correlacion
## 1 17 28 1.0000000
## 2 17 46 1.0000000
## 3 17 49 1.0000000
## 4 39 7 1.0000000
## 5 39 64 1.0000000
## 6 39 68 1.0000000
## 7 62 26 1.0000000
## 8 62 31 1.0000000
## 9 62 40 1.0000000
## 10 105 25 1.0000000
## 11 105 28 1.0000000
## 12 105 46 1.0000000
## 13 11 52 1.0000000
## 14 11 58 1.0000000
## 15 11 94 1.0000000
## 16 110 73 0.7867958
## 17 21 20 0.7125253
## 18 50 22 0.7125253
## 19 21 6 0.5897436
## 20 21 23 0.5897436
## 21 50 6 0.5897436
## 22 50 21 0.5897436
## 23 110 42 0.5897436
## 24 110 86 0.5897436
## 25 48 25 0.5606119
## 26 48 27 0.5606119
## 27 48 28 0.5606119
Ahora determinar las frecuencias
Por medio de table que es una función que identifica frecuencias
masFrecuentes <- table(recomendaciones$Recomendada)
masFrecuentes <- sort(masFrecuentes, decreasing = TRUE)
masFrecuentes <- data.frame(masFrecuentes)
colnames(masFrecuentes) <- c("Recomendada", "Frecuencia")
masFrecuentes <- filter(masFrecuentes, Frecuencia > 1)
masFrecuentes
## Recomendada Frecuencia
## 1 28 3
## 2 6 2
## 3 25 2
## 4 46 2
Finalmente traemos solo el nombre de las películas recomendadas
Para este usuario. Que fue el usuario
Se utiliza una combinacipn de filter, select ambos combiandos con %>%
Se utiliza rbind para ir agregando el resultado del filter y el select juntos
nomPelicula <- NULL # Vector vacio
if (nrow(masFrecuentes) > 0) {
for (p in 1:nrow(masFrecuentes)) {
nomPelicula <- rbind(nomPelicula, filter (peliculas, movieId == masFrecuentes[p,1]) %>%
select(title))
}
nomPelicula <- c(nomPelicula)
} else {
print("No hay frecuencia de recomendaciones mayor 1. O Sea que hay muy pocas recomendaciones para el usuario. Se le debe elegir recomendar solo las películas con correlación más alta.")
recomendaciones
for (p in 1:nrow(recomendaciones)) {
nomPelicula <- rbind(nomPelicula, filter (peliculas, movieId == recomendaciones[p,2]) %>%
select(title))
}
nomPelicula
}
Ahora solo resta agregar al columna a dataframe masFrecuente o a recomendaciones en caso de poca frecuencia
if (nrow(masFrecuentes) > 0) {
masFrecuentes <- mutate(masFrecuentes, nomPelicula$title) #Agregar el nombre
masFrecuentes <- masFrecuentes[,-2] # quitar la columna dos
colnames(masFrecuentes) <- c("Recomendada", "Nombre")
masFrecuentes
} else {
print("No hay frecuencia de recomendaciones mayor 1. O Sea que hay muy pocas recomendaciones. Elegir otro usuario. Se muestran las películas con correlaciones más altas")
recomendaciones <- recomendaciones[,-1] # quitar la columna 1 y 3
recomendaciones <- recomendaciones[,-2] # quitar la columna 1 y 3
recomendaciones <- data.frame(recomendaciones)
recomendaciones <- mutate(recomendaciones, nomPelicula$title) #Agregar el nombre
colnames(recomendaciones) <- c("Recomendada", "Nombre")
recomendaciones
}
## Recomendada Nombre
## 1 28 Persuasion (1995)
## 2 6 Heat (1995)
## 3 25 Leaving Las Vegas (1995)
## 4 46 How to Make an American Quilt (1995)