首页 文章

从数据框创建稀疏矩阵

提问于
浏览
15

我正在做一项任务,我正在尝试为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

所以最后我想要这样的东西:列是电影ID,行是用户ID

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

所以解释是这样的:用户2将电影1评为3星,用户3将电影2评为3星,以此类推其他用户和电影 . 我的数据框中有大约8500000行,我的代码需要大约30-45分钟来创建此用户项矩阵,我想得到任何建议

2 回答

  • 14

    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 方法 . )

  • 9

    这可能比循环更快 .

    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 转换为data.table(不进行复制) . 如果你的数据集是巨大的,那可能会有所不同......

相关问题