2012-01-17 18 views
0

假設我是用電影分級的這組數據:http://www.grouplens.org/node/73如何使用R項目創建電影評級的矢量矩陣?

它包含格式爲 用戶ID :: movieID ::評級::時間戳

給出文件收視率,我想構造特徵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腳本來做同樣的事情,但我敢打賭有更有效的方法來實現這一點。

+0

重塑最有可能會工作,或plyr包上的東西 – aatrujillob 2012-01-17 01:28:31

+0

除了使用稀疏矩陣,我建議查看有關R和稀疏矩陣的其他問題,以獲得相關問題的想法:http:// stackoverflow .com/questions/tagged/r +稀疏矩陣 – Iterator 2012-01-19 13:01:09

回答

3

您可以在reshape2包中使用dcast函數,但生成的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

這個差不多可行!只是一個小問題,我的文件上的分隔符是雙冒號「::」,但似乎R抱怨他們。有沒有辦法解決這個問題,還是隻能在文件中做一個簡單的替換? – 2012-01-17 06:39:55

+0

@DanQ:我已經更新了答案來處理您的文件格式。 – 2012-01-17 06:58:33

+1

由於矩陣可能非常稀疏,請查看處理備用矩陣的各種軟件包。 – 2012-01-17 07:27:07

0

從該網站指出,前一個問題,看來你要代表

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

這應該是「易」與8 GB你another question引用。另外,總長度小於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 GB,所以這是很好的。

已經這樣做了,你現在就運行到嚴重的問題。 k均值(從你的迴應上較早較早答題)不會遺漏值

> 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倍作爲起始數據大小的內存很多。您是否使用較小的數據集進行了分析?

+0

dcast函數允許選擇一個填充值(我選擇0),以便解決缺失的值。然而,你是對的,我擔心這些媒介將佔用多少內存,以及對它們執行k-means的必要記憶......我不知道8GB是否足夠。 (儘管我能夠從grouplens處理1M數據集) – 2012-01-20 09:00:32

0

很簡單,您可以使用Matrix包中的sparseMatrix將其表示爲稀疏矩陣。

只需創建一個3列座標對象列表,即形式爲(i, j, value),比如在名爲myDF的數據框中。然後,執行mySparseMat <- sparseMatrix(i = myDF$i, j = myDF$j, x = myDF$x, dims = c(numRows, numCols) - 您需要確定行數和列數,否則最大索引將用於決定矩陣的大小。

它就是這麼簡單。將稀疏數據存儲在密集矩陣中是不恰當的,如果不是怪誕的話。