Создание разреженной матрицы из кадра данных
Я выполняю задание, где я пытаюсь создать совместную фильтрующую модель для данных приза Netflix. Данные, которые я использую, находятся в файле CSV, который я легко импортирую в фрейм данных. Теперь мне нужно создать разреженную матрицу, состоящую из Пользователей в виде строк и фильмов в качестве столбцов, и каждая ячейка заполняется соответствующим значением рейтинга. Когда я пытаюсь отобразить значения в кадре данных, мне нужно запустить цикл для каждой строки в фрейме данных, который занимает много времени в R, пожалуйста, любой может предложить лучший подход. Вот пример кода и данных:
buildUserMovieMatrix <- function(trainingData)
{
UIMatrix <- Matrix(0, nrow = max(trainingData$UserID), ncol = max(trainingData$MovieID), sparse = T);
for(i in 1:nrow(trainingData))
{
UIMatrix[trainingData$UserID[i], trainingData$MovieID[i]] = trainingData$Rating[i];
}
return(UIMatrix);
}
Пример данных в фрейме данных, из которого создается разреженная матрица:
MovieID UserID Rating
1 1 2 3
2 2 3 3
3 2 4 4
4 2 6 3
5 2 7 3
Итак, в конце концов я хочу что-то вроде этого:
Столбцы - это идентификаторы фильмов, а строки - это идентификаторы пользователей.
1 2 3 4 5 6 7
1 0 0 0 0 0 0 0
2 3 0 0 0 0 0 0
3 0 3 0 0 0 0 0
4 0 4 0 0 0 0 0
5 0 0 0 0 0 0 0
6 0 3 0 0 0 0 0
7 0 3 0 0 0 0 0
Итак, интерпретация выглядит примерно так: user 2 rated movie 1 as 3 star, user 3 оценил фильм 2 как 3 звезды и так далее для других пользователей и фильмов. В моем кадре данных около 8500000 строк, для которых мой код занимает около 30-45 минут, чтобы создать эту матрицу пользовательских элементов, я хотел бы получить любые предложения
Ответы
Ответ 1
В пакете Matrix
есть конструктор, созданный специально для вашего типа данных:
library(Matrix)
UIMatrix <- sparseMatrix(i = trainingData$UserID,
j = trainingData$MovieID,
x = trainingData$Rating)
В противном случае вам может понравиться знать об этой классной функции функции [
, известной как индексация матрицы. Возможно, вы пробовали:
buildUserMovieMatrix <- function(trainingData) {
UIMatrix <- Matrix(0, nrow = max(trainingData$UserID),
ncol = max(trainingData$MovieID), sparse = TRUE);
UIMatrix[cbind(trainingData$UserID,
trainingData$MovieID)] <- trainingData$Rating;
return(UIMatrix);
}
(но я определенно рекомендую подход sparseMatrix
.)
Ответ 2
Это, вероятно, будет быстрее, чем цикл.
library(reshape2)
m <- dcast(df,UserID~MovieID,fill=0)[-1]
m
# 1 2
# 1 3 0
# 2 0 3
# 3 0 4
# 4 0 3
# 5 0 3
Если вы используете data.tables, это будет намного быстрее:
library(data.table)
DT <- as.data.table(df)
m <- dcast(DT,UserID~MovieID,fill=0)[-1]
И, как я уверен, кто-то укажет, вы можете использовать это вместо
setDT(df)
m <- dcast(df,UserID~MovieID,fill=0)[-1]
Это преобразует df
в таблицу данных (не делая копию). если ваш набор данных огромен, это может иметь значение...