我需要更新稀疏矩阵中的某些列,但操作需要花费很长时间才能完成。
我有一个稀疏的矩阵,其行数少于3M行,大约有1500列。我还有一个具有相同行数的数据框,但只有10列。我想用data.frame中的值更新矩阵中的某些列索引。
使用普通矩阵执行此操作时没有问题,但在使用稀疏矩阵进行此操作时,即使只有一列也需要很长时间。
以下是我正在使用的代码,需要更改哪些代码才能有效运行?
library(Matrix)
x <- Matrix(0, nrow = 2678748, ncol = 1559, sparse = TRUE)
df <- data.frame(replicate(5,sample(0:1,2678748,rep = TRUE)))
var_nums <- sample(1:1559,size = 5)
for (i in 1:5){
x[,var_nums[i]] <- df[,i]
}
答案 0 :(得分:1)
我可以使用Matrix::cBind
函数并消除for
循环,在1秒内完成它。
library(Matrix)
x <- Matrix(0, nrow = 2678748, ncol = 1559, sparse = TRUE)
df <- data.frame(replicate(5,sample(0:1,2678748,rep = TRUE)))
var_nums <- sample(1:1559,size = 5)
t <- Sys.time()
x <- x[,-var_nums]
x <- Matrix::cBind(x, Matrix::as.matrix(df))
Sys.time()-t
Time difference of 0.541054 secs
保留订单(仍然不到1秒!)
library(Matrix)
x <- Matrix(0, nrow = 2678748, ncol = 1559, sparse = TRUE)
df <- data.frame(replicate(5,sample(0:1,2678748,rep = TRUE)))
colnames(x) <- paste("col", 1:ncol(x))
col.order <- colnames(x)
cols <- sample(colnames(x),size = 5)
colnames(df) <- cols
t <- Sys.time()
x <- x[,-which(colnames(x) %in% cols)]
x <- Matrix::cBind(x, Matrix::as.matrix(df) )
x <- x[,col.order]
Sys.time()-t
> Time difference of 0.550012 secs
# Proof that order is preserved:
identical(colnames(x), col.order)
TRUE
答案 1 :(得分:1)
Yuo可以使用i
j
,x
,sparseMatrix
表示法
library(Matrix)
# data
set.seed(1)
# Changed the dim size to fit in my laptop memory
nc=10
nr=100
n=5
df <- data.frame(replicate(n,sample(0:1,nr,rep = TRUE)))
var_nums <- sample(1:nc,size = n)
#Yours
x <- Matrix(0, nrow = nr, ncol = nc, sparse = TRUE)
for (i in 1:n){
x[,var_nums[i]] <- df[,i]
}
# new version
i = ((which(df==1)-1) %% nr) +1
j = rep(var_nums, times=colSums(df))
y = sparseMatrix(i=i, j=j, x=1, dims=c(nrow(df), nc))
all.equal(x, y, check.attributes=FALSE)
比较速度
f1 <- function(){
for (i in 1:n){
x[,var_nums[i]] <- df[,i]
}
x
}
f2 <- function(){
i = ((which(df==1)-1) %% nr) +1
j = rep(var_nums, times=colSums(df))
y = sparseMatrix(i=i, j=j, x=1, dims=c(nrow(df), nc))
y
}
microbenchmark::microbenchmark(f1(), f2())
Unit: milliseconds
expr min lq mean median uq max neval cld
f1() 4.594229 4.694205 5.010071 4.770475 4.891649 12.666554 100 b
f2() 1.274745 1.298663 1.464237 1.329534 1.392146 7.153076 100 a
尝试更大的
nc=100
nr=10000
n=50
set.seed(1)
df <- data.frame(replicate(n,sample(0:1,nr,rep = TRUE)))
var_nums <- sample(1:nc,size = n)
x <- Matrix(0, nrow = nr, ncol = nc, sparse = TRUE)
all.equal(f1(), f2(), check.attributes=FALSE)
microbenchmark::microbenchmark(f1(), f2(), times=1)
Unit: milliseconds
expr min lq mean median uq max neval
f1() 21605.60251 21605.60251 21605.60251 21605.60251 21605.60251 21605.60251 1
f2() 60.87275 60.87275 60.87275 60.87275 60.87275 60.87275 1
答案 2 :(得分:0)
这有点麻烦,但您可以将所需的列绑定在一起,就像这样
Nc = NCOL(x)
Matrix(cbind(
x[, 1:(var_nums[1]-1)],
df[, 1],
x[, (var_nums[1]+1):(var_nums[2]-1)],
df[, 2],
x[, (var_nums[2]+1):(var_nums[3]-1)],
df[, 3],
x[, (var_nums[3]+1):(var_nums[4]-1)],
df[, 4],
x[, (var_nums[4]+1):(var_nums[5]-1)],
df[, 5],
x[, (var_nums[5]+1):Nc]),
sparse = TRUE)
当df只插入5列时,这并不算太糟糕。如果df具有更多或不同数量的列,则不同的语法可能更合适。无论如何,绑定列相对较快。