2014-10-05 41 views
11

Sto facendo un compito in cui sto cercando di creare un modello di filtro collaborativo per i dati sui premi Netflix. I dati che sto usando sono in un file CSV che ho facilmente importato in un frame di dati. Ora quello che devo fare è creare una matrice sparsa costituita dagli utenti come le righe e film come le colonne e ogni cella è riempita dal corrispondente valore di valutazione. Quando provo a mappare i valori nel frame di dati, ho bisogno di eseguire un ciclo per ogni riga nel frame di dati, che richiede molto tempo in R, per favore qualcuno può suggerire un approccio migliore. Ecco il codice di esempio e di dati:Crea matrice sparsa da un riquadro dati

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); 
} 

campione di dati nel dataframe da cui viene creata la matrice sparsa:

MovieID UserID Rating 
1  1  2  3 
2  2  3  3 
3  2  4  4 
4  2  6  3 
5  2  7  3 

Così, alla fine voglio qualcosa di simile: Le colonne sono gli ID di film e le file sono gli ID utente

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 

Quindi l'interpretazione è qualcosa di simile: l'utente 2 valutazione movie 1 come 3 stelle, 3 utente valutato il film 2 come 3 STA r e così via per gli altri utenti e film. Ci sono circa 8,5 milioni le righe nel mio frame di dati per i quali il mio codice richiede solo circa 30-45 minuti per creare questa matrice oggetto utente, vorrei ottenere qualche suggerimento

risposta

12

Il pacchetto Matrix ha un costruttore realizzata appositamente per il tipo di dati:

library(Matrix) 
UIMatrix <- sparseMatrix(i = trainingData$UserID, 
         j = trainingData$MovieID, 
         x = trainingData$Rating) 

In caso contrario, come si potrebbe sapere su questa funzione interessante della funzione [ nota come indicizzazione matrice. Il vostro potrebbe avere provato:

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); 
} 

(ma consiglio vivamente l'approccio sparseMatrix su questo.)

+0

Grazie mille !!!, funziona perfettamente. – user37940

+0

L'approccio sparseMatrix funziona più velocemente del secondo approccio, grazie. :) – user37940

9

questo sarà probabilmente più veloce di un ciclo.

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 

Se si utilizza data.tables, sarà un sacco più veloce:

library(data.table) 
DT <- as.data.table(df) 
m <- dcast(DT,UserID~MovieID,fill=0)[-1] 

E come sono sicuro che qualcuno sottolineare, è possibile utilizzare questo invece

setDT(df) 
m <- dcast(df,UserID~MovieID,fill=0)[-1] 

Converte df in un file data.table (senza fare una copia). se il set di dati è enorme, che possono fare la differenza ...

+0

Grazie mille !!! – user37940

+1

C'è un piccolo problema con questo approccio, tuttavia, questo approccio non mappa correttamente USERID e MOVIEIDs per es. l'USER 11 mancava dai dati di allenamento, quindi ora nella riga 11 ho l'ID utente e la classificazione ID film per l'utente 12 e successivamente tutte le righe sono spostate di 1, ho 10916 utenti nel mio set di treni e voglio mantenere tutti nella mia matrice User Item, nel caso in cui mancasse un utente dai miei dati di allenamento, potrei contrassegnare il vettore dell'intera riga come zero, questo eviterebbe qualsiasi discrepanza nel frame dei dati di addestramento e nella mia matrice, puoi suggerire qualche altro approccio, grazie – user37940

Problemi correlati