【问题标题】:Convert a list with various vector length (Compressed Row Storage) into sparseMatrix in R将具有各种向量长度(压缩行存储)的列表转换为 R 中的 sparseMatrix
【发布时间】:2017-05-04 14:23:22
【问题描述】:

我使用DynamicColumns 结构将我的稀疏数据存储在 MariaDB 表中。 当我将其导入 R 时,我得到以下 db_frame 数据框:

db_frame <- dbGetQuery(mydb, "SELECT uid, column_json(groups) FROM matrix")
db_frame
  uid                      column_json(groups)
1   8              {"33755311":1,"58534882":1}
2   9                           {"75338985":1}
3  15               {"5445504":1,"58534882":1}
4  16 {"14897324":1,"22522055":1,"68471405":1}
5  20              {"22522055":1,"48940689":1}

我的目标是将它从上面的压缩行存储转换为下面的 sparse-format(!) 矩阵:

   14897324 22522055 33755311 48940689 5445504 58534882 68471405 75338985
8         .        .        1        .       .        1        .        .
9         .        .        .        .       .        .        .        1
15        .        .        .        .       1        1        .        .
16        1        1        .        .       .        .        1        .
20        .        1        .        1       .        .        .        .

我已经通过两种方式做到了这一点,但在我看来,这两种方式都非常低效。 在现实生活中,变量数(列)约为 2-3K,观察数(行)约为 100 万。所以我这两种方法都需要很长时间才能完成工作(天)。

还有其他更优雅的方式来进行这种转换吗? 提前谢谢!

UPD:有两个 R 格式的数据框的链接:

  1. db_frame - 来自示例 5 观察的数据框
  2. db_frame_10K - 用于速度测试的具有 10K 观察值的真实数据框

UPD2:转换数据帧的速度比较表10K observation
Core i3 2.93 Ghz

Method1 我的 162-188 秒
方法 2 我的 94-102 秒
Method3 @amatsuo_net 47-57 秒(但不是完全需要的格式)
Method4 @amatsuo_net+我的6秒

我的两种方法供您参考:

第一步是将db_frame 数据框转换为更友好的列表,以便可以从中提取每个观察值的变量名称。

library("rjson")
var_list <- lapply(db_frame[,-1],fromJSON)
var_list_names <- lapply(var_list,names)
var_list_names
[[1]]
[1] "33755311" "58534882"

[[2]]
[1] "75338985"

[[3]]
[1] "5445504"  "58534882"

[[4]]
[1] "14897324" "22522055" "68471405"

[[5]]
[1] "22522055" "48940689"

变量和观察名称列表:

groups <- sort(unique(unlist(var_list_names)))
groups
[1] "14897324" "22522055" "33755311" "48940689" "5445504"  "58534882" "68471405" "75338985"
uids <- db_frame$uid
uids
[1] "8"  "9"  "15" "16" "20"

------------- 方法一使用“for i”循环

row_number = length(uids)
col_number = length(groups)

# creating empty sparse matrix M1
M1 <- sparseMatrix(dims = c(row_number,col_number), i={}, j={}, x=1)
rownames(M1) <- uids
colnames(M1) <- groups

# filling M1
for (i in 1:row_number) {
      M1[i,var_list_names[[i]]] <-1
}
M1

-------------- 使用“reshape2”的方法2

library("reshape2")
long <- melt(var_list)
long
   value       L2 L1
1      1 33755311  1
2      1 58534882  1
3      1 75338985  2
4      1  5445504  3
5      1 58534882  3
6      1 14897324  4
7      1 22522055  4
8      1 68471405  4
9      1 22522055  5
10     1 48940689  5

i=long$L1
j=match(long[,"L2"],groups)

M2 <-sparseMatrix(i=i, j=j, x=1)
rownames(M2) <- uids
colnames(M2) <- groups
M2

【问题讨论】:

    标签: r sparse-matrix reshape


    【解决方案1】:

    感谢@amatsuo_net 将我指向data.table 包中的rbindlist 函数。
    我稍微简化了他的代码并添加了对稀疏格式的转换。
    测试 10K 观察的转换时间令人印象深刻 6 秒

    -------------- 方法 4 使用“rbindlist”

    library(RMySQL)
    library(Matrix)
    library(rjson)
    library(data.table)
    library(magrittr)
    
    df <- dbGetQuery(mydb, "SELECT uid, column_json(groups) FROM matrix")    
    
    # "rbindlist" does all the work    
    M3 <- lapply(df[,-1],fromJSON) %>% rbindlist(fill=TRUE)
    
    # replace NA with 0 (required for sparsematrix type)
    M3[is.na(M3)] <- 0 
    # converting to sparsematrix type
    M3 <- as(as.matrix(M3), "sparseMatrix")
    
    # make some order :)
    M3 <- M3[, order(as.integer(colnames(M3)))]
    row.names(M3) <- df$uid
    

    【讨论】:

      【解决方案2】:

      我认为这会起作用,但不确定它的效率如何,因为我没有测试数据。

      library(data.table)
      library(magrittr)
      split(df, seq(nrow(df))) %>% 
        lapply(function(x) {
          dt <- data.table(t(unlist(fromJSON(x$column_json))))
          dt[, id := x$uid]
        }) %>% 
        rbindlist(fill = TRUE)
      

      【讨论】:

      • 谢谢!关闭,但不完全是所需的。我已经上传了源数据框。您可以自己检查结果。和其他问题 - 如何将其转换为稀疏格式?由于大量内存消耗,最好在开始时使用。
      • 您也可以在对照表中查看您的代码效率。 (见 UPD2)
      • 很高兴我提供了帮助(尽管这不是您真正需要的):)
      猜你喜欢
      • 2017-02-28
      • 2018-08-06
      • 2017-10-31
      • 2013-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多