Как создать векторную матрицу рейтингов фильмов, используя проект R? - PullRequest
0 голосов
/ 17 января 2012

Предположим, я использую этот набор данных рейтингов фильмов: http://www.grouplens.org/node/73

Содержит оценки в файле, отформатированном как userID :: movieID :: rating :: timestamp

Учитывая это,Я хочу построить матрицу объектов в проекте R, где каждая строка соответствует пользователю, а каждый столбец указывает оценку, которую пользователь дал фильму (если есть).

Пример, если файл данных содержит

1::1::1::10
2::2::2::11
1::2::3::12
2::1::5::13
3::3::4::14

Тогда матрица вывода будет выглядеть следующим образом:

UserID, Movie1, Movie2, Movie3
1, 1, 3, NA
2, 5, 2, NA
3, NA, NA, 3

Итак, есть ли какой-то встроенный способ для достижения этого в R-проекте.Я написал простой скрипт на python, чтобы сделать то же самое, но держу пари, что есть более эффективные способы сделать это.

Ответы [ 3 ]

3 голосов
/ 17 января 2012

Вы можете использовать функцию dcast в пакете reshape2, но результирующий data.frame может быть огромным (и разреженным).

d <- read.delim(
  "u1.base", 
  col.names = c("user", "film", "rating", "timestamp")
)
library(reshape2)
d <- dcast( d, user ~ film, value.var = "rating" )

Если ваши поля разделены двойными двоеточиями, вы не можете использовать sep аргумент read.delim, который должен быть только одним символом. Если вы уже выполняете некоторую предварительную обработку вне R, это проще сделать там (например, в Perl это будет просто s/::/\t/g), но вы также можете сделать это в R: прочитать файл как один столбец, разделить строки и объединить результат.

d <- read.delim("a")
d <- as.character( d[,1] )   # vector of strings
d <- strsplit( d, "::" )     # List of vectors of strings of characters
d <- lapply( d, as.numeric ) # List of vectors of numbers
d <- do.call( rbind, d )     # Matrix
d <- as.data.frame( d )
colnames( d ) <- c( "user", "movie", "rating", "timestamp" )
0 голосов
/ 19 января 2012

Проще говоря, вы можете представить его как разреженную матрицу, используя sparseMatrix из пакета Matrix.

Просто создайте список объектов координат с тремя столбцами, то есть в форме (i, j, value), скажемв фрейме данных с именем myDF.Затем выполните mySparseMat <- sparseMatrix(i = myDF$i, j = myDF$j, x = myDF$x, dims = c(numRows, numCols) - вам нужно определить количество строк и столбцов, иначе максимальные индексы будут использоваться для определения размера матрицы.

Все просто.Хранение разреженных данных в плотной матрице неуместно, если не гротескно.

0 голосов
/ 19 января 2012

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

> print(object.size(integer(10000 * 72000)), units="Mb")
2746.6 Mb

, что должно быть «просто» с 8 ГБ, на которые вы ссылаетесь в другой вопрос ,Кроме того, общая длина меньше максимальной длины вектора в R, так что это тоже должно быть в порядке.Но посмотрите конец ответа для важного предостережения!

Я создал вне R версию файла данных с разделителями табуляцией.Затем я прочитал информацию, которая меня интересовала

what <- list(User=integer(), Film=integer(), Rating=numeric(), NULL)
x <- scan(fl, what)

, и 'NULL' отбрасывает неиспользуемые данные временной метки.Записи «Пользователь» и «Фильм» не являются последовательными, и numeric() на моей платформе занимает в два раза больше памяти, чем integer(), поэтому я преобразовал Пользователь и Фильм в коэффициент, а Рейтинг в целое число () путем удвоения (оригинал)оценки от 1 до 5 с шагом 1/2).

x <- list(User=factor(x$User), Film=factor(x$Film),
          Rating=as.integer(2 * x$Rating))

Затем я выделил матрицу

ratings <- matrix(NA_integer_ ,
                 nrow=length(levels(x$User)),
                 ncol=length(levels(x$Film)),
                 dimnames=list(levels(x$User), levels(x$Film)))

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

ratings[cbind(x$User, x$Film)] <- x$Rating

Это шаг, при котором использование памяти максимально.Затем я удалил бы ненужную переменную

rm(x)

Функция gc() сообщает мне, сколько памяти я использовал ...

> gc()
            used   (Mb) gc trigger   (Mb)  max used   (Mb)
Ncells    140609    7.6     407500   21.8    350000   18.7
Vcells 373177663 2847.2  450519582 3437.2 408329775 3115.4

... чуть более 3 Гбтак что это хорошо.

Сделав это, вы столкнетесь с серьезными проблемами.kmeans (из вашего ответа на вопросы по более раннему ответу) не будет работать с пропущенными значениями

> m = matrix(rnorm(100), 5)
> m[1,1]=NA
> kmeans(m, 2)
Error in do_one(nmeth) : NA/NaN/Inf in foreign function call (arg 1)

, и как очень грубое практическое правило, я ожидаю, что для готовых решений R требуется 3-5В разы больше памяти, чем начальный размер данных.Проработали ли вы анализ с меньшим набором данных?

...