双向频率table后跟矩阵乘法-高运行时间
Two-way frequency table followed by matrix multiplication - high running time
我是 R 的新手,正在尝试为数据帧或矩阵中的任意列组合计算固定矩阵与二维频率 table 之间的乘积,并将其除以序列长度(又名行数为 15),问题是 运行 时间在 1K 序列(1K 列)上执行时急剧增加。目标是尽可能多地使用它(超过 10 分钟,对于 10K 可能超过 1 小时)
mat1 <- matrix(sample(LETTERS),ncol = 100,nrow = 15)
mat2 <- matrix(sample(abs(rnorm(26,0,3))),ncol=26,nrow=26)
rownames(mat2) <- LETTERS
colnames(mat2) <- LETTERS
diag(mat2) <- 0
test_vec <- c()
for (i in seq(ncol(mat1)-1)){
for(j in seq(i+1,ncol(mat1))){
s2 <- table(mat1[,i],mat1[,j]) # create 2-way frequency table
mat2_1 <- mat2
mat2_1 <- mat2_1[rownames(mat2_1) %in% rownames(s2),
colnames(mat2_1) %in% colnames(s2)]
calc <- ((1/nrow(mat1))*sum(mat2_1*s2))
test_vec <- append(test_vec,calc)
}}
感谢您的帮助。
这是一种将 mat1 转换为 data.table 并将所有列转换为因子的方法,并使用 table(..., exclude=NULL)
library(data.table)
m=as.data.table(mat1)[,lapply(.SD, factor, levels=LETTERS)]
g = combn(colnames(m),2, simplify = F)
result = sapply(g, function(x) sum(table(m[[x[1]]], m[[x[2]]], exclude=NULL)*mat2)/nrow(m))
检查是否相等:
sum(result-test_vec>1e-10)
[1] 0
这里有4950种组合(100*99/2),但是组合的数量会随着nrow(mat1)的增加而快速增加(正如你所指出的)。在这种情况下,您可能会发现并行化版本效果很好。
library(doParallel)
library(data.table)
registerDoParallel()
m=as.data.table(mat1)[,lapply(.SD, factor, levels=LETTERS)]
g = combn(colnames(m),2, simplify = F)
result = foreach(i=1:length(g), .combine=c) %dopar%
sum(table(m[[g[[i]][1]]], m[[g[[i]][2]]], exclude=NULL)*mat2)
result = result/nrow(m)
我是 R 的新手,正在尝试为数据帧或矩阵中的任意列组合计算固定矩阵与二维频率 table 之间的乘积,并将其除以序列长度(又名行数为 15),问题是 运行 时间在 1K 序列(1K 列)上执行时急剧增加。目标是尽可能多地使用它(超过 10 分钟,对于 10K 可能超过 1 小时)
mat1 <- matrix(sample(LETTERS),ncol = 100,nrow = 15)
mat2 <- matrix(sample(abs(rnorm(26,0,3))),ncol=26,nrow=26)
rownames(mat2) <- LETTERS
colnames(mat2) <- LETTERS
diag(mat2) <- 0
test_vec <- c()
for (i in seq(ncol(mat1)-1)){
for(j in seq(i+1,ncol(mat1))){
s2 <- table(mat1[,i],mat1[,j]) # create 2-way frequency table
mat2_1 <- mat2
mat2_1 <- mat2_1[rownames(mat2_1) %in% rownames(s2),
colnames(mat2_1) %in% colnames(s2)]
calc <- ((1/nrow(mat1))*sum(mat2_1*s2))
test_vec <- append(test_vec,calc)
}}
感谢您的帮助。
这是一种将 mat1 转换为 data.table 并将所有列转换为因子的方法,并使用 table(..., exclude=NULL)
library(data.table)
m=as.data.table(mat1)[,lapply(.SD, factor, levels=LETTERS)]
g = combn(colnames(m),2, simplify = F)
result = sapply(g, function(x) sum(table(m[[x[1]]], m[[x[2]]], exclude=NULL)*mat2)/nrow(m))
检查是否相等:
sum(result-test_vec>1e-10)
[1] 0
这里有4950种组合(100*99/2),但是组合的数量会随着nrow(mat1)的增加而快速增加(正如你所指出的)。在这种情况下,您可能会发现并行化版本效果很好。
library(doParallel)
library(data.table)
registerDoParallel()
m=as.data.table(mat1)[,lapply(.SD, factor, levels=LETTERS)]
g = combn(colnames(m),2, simplify = F)
result = foreach(i=1:length(g), .combine=c) %dopar%
sum(table(m[[g[[i]][1]]], m[[g[[i]][2]]], exclude=NULL)*mat2)
result = result/nrow(m)