【问题标题】:Create Sparse Matrix from a data frame从数据框创建稀疏矩阵
【发布时间】:2014-11-30 05:14:03
【问题描述】:

我正在执行一项任务,我正在尝试为 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 分钟来创建这个用户项矩阵,我想得到任何建议

【问题讨论】:

    标签: r machine-learning sparse-matrix


    【解决方案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 方法。)

    【讨论】:

    • 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 转换为适当的data.table(不制作副本)。如果您的数据集非常庞大,那可能会有所不同...

    【讨论】:

    • 这种方法有一个小问题,这种方法不能正确映射 USERID 和 MOVIEID,例如训练数据中缺少 USER 11,所以现在在第 11 行中,我有用户 12 的用户 ID 和电影 ID 评级,随后所有行都移动了 1,我的火车集中有 10916 个用户,我想保留所有这些都在我的用户项矩阵中,如果我的训练数据中缺少用户,我可以将整个行向量标记为零,这将防止训练数据数据框和我的矩阵中的任何不匹配,你能建议一些其他的吗方法,谢谢
    猜你喜欢
    • 2017-03-31
    • 2012-01-10
    • 2021-10-11
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    相关资源
    最近更新 更多