将具有各种向量长度(压缩行存储)的列表转换为 R 中的稀疏矩阵
Convert a list with various vector length (Compressed Row Storage) into sparseMatrix in R
我使用 DynamicColumns 结构将我的稀疏数据存储在 MariaDB table 中。
当我将它导入 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 格式数据框的链接:
- db_frame - 来自示例 5 观察结果的数据框
- db_frame_10K - 具有 10K 个观测值的真实数据帧,用于速度测试
UPD2: 转换数据帧 10K observation
的速度比较 TABLE
酷睿 i3 2.93GHz
Method1 My 162-188 sec
Method2 My 94-102 sec
Method3 @amatsuo_net 47-57 sec (but not exactly required format)
Method4 @amatsuo_net+My 6 sec
供大家参考我的两种方法:
第一步是将 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"
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
我认为这会奏效,但不确定它的效率如何,因为我没有测试数据。
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)
感谢 @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
我使用 DynamicColumns 结构将我的稀疏数据存储在 MariaDB table 中。
当我将它导入 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 格式数据框的链接:
- db_frame - 来自示例 5 观察结果的数据框
- db_frame_10K - 具有 10K 个观测值的真实数据帧,用于速度测试
UPD2: 转换数据帧 10K observation
的速度比较 TABLE
酷睿 i3 2.93GHz
Method1 My 162-188 sec Method2 My 94-102 sec Method3 @amatsuo_net 47-57 sec (but not exactly required format) Method4 @amatsuo_net+My 6 sec
供大家参考我的两种方法:
第一步是将 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"
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
我认为这会奏效,但不确定它的效率如何,因为我没有测试数据。
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)
感谢 @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