Создание разреженной матрицы из кадра данных

Я выполняю задание, где я пытаюсь создать совместную фильтрующую модель для данных приза 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 в таблицу данных (не делая копию). если ваш набор данных огромен, это может иметь значение...