R 如何将矩阵的每一行与所有其他行进行矢量化比较
我试图将矩阵中的每一行与所有其他行进行比较,以计算每一行与所有其他行之间的差异数。然后,结果存储在矩阵的左下角三角形中 因此,例如,当将行m[1,]与行m[2,]和m[3]进行比较时,差异计数存储在结果矩阵中mat[c(2:3),1]的位置 我的问题是,我的输入矩阵最多可以有1e+07行,而当前的实现(速度和内存)由于n^2比较而无法扩展。建议和帮助将不胜感激R 如何将矩阵的每一行与所有其他行进行矢量化比较,r,loops,matrix,vectorization,R,Loops,Matrix,Vectorization,我试图将矩阵中的每一行与所有其他行进行比较,以计算每一行与所有其他行之间的差异数。然后,结果存储在矩阵的左下角三角形中 因此,例如,当将行m[1,]与行m[2,]和m[3]进行比较时,差异计数存储在结果矩阵中mat[c(2:3),1]的位置 我的问题是,我的输入矩阵最多可以有1e+07行,而当前的实现(速度和内存)由于n^2比较而无法扩展。建议和帮助将不胜感激 diffMatrix <- function(x) { rows <- dim(x)[1] #num of rows
diffMatrix <- function(x) {
rows <- dim(x)[1] #num of rows
cols <- dim(x)[2] #num of columns
if (rows <= 1) stop("'x' must have atleast two rows")
#potential failure point
mat <- matrix(, rows, rows)
# fill bottom left triangle columns ignoring the diagonal
for (row in 1:(rows-1)) {
rRange <- c((1+row):rows)
m <- matrix(x[row,], nrow=rows-row, ncol=cols, byrow = T)
mat[rRange, row] <- rowSums(m != x[-1:-row, ])
}
return (mat)
}
m <- matrix(sample(1:12, 12, replace=T), ncol=2, byrow=TRUE)
m
# [,1] [,2]
#[1,] 8 1
#[2,] 4 1
#[3,] 8 4
#[4,] 4 5
#[5,] 3 1
#[6,] 2 2
x <- diffMatrix(m)
x
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] NA NA NA NA NA NA
#[2,] 1 NA NA NA NA NA
#[3,] 1 2 NA NA NA NA
#[4,] 2 1 2 NA NA NA
#[5,] 1 1 2 2 NA NA
#[6,] 2 2 2 2 2 NA
m <- matrix(sample(1:5, 50000, replace=T), ncol=10, byrow=TRUE)
# system.time(x <- diffMatrix(m))
# user system elapsed
# 20.39 0.38 21.43
diffMatrix这里有一个使用.Call的替代方法(似乎有效,但我不能保证):
库(内联)
ff=c功能(sig=c(R_mat=“矩阵”),主体
SEXP mat、dims、ans、dimans;
保护(dims=getAttrib(R_mat,R_DimSymbol));
保护(dimans=allocVector(INTSXP,2));
R_len_t*pdims=整数(dims),*pdimans=整数(DIMAN);
保护(ans=allocVector(INTSXP,pdims[0]*pdims[0]);
R_len_t*pans=整数(ans);
pdimans[0]=pdims[0];
pdimans[1]=pdims[0];
对于(int-ina=0;ina m2如果你要走C
路线,我强烈建议你去Rcpp
。它提供了大量的语法糖分,使底层C更易于编写。@Scottrichie:“Rcpp”在我2014年的“待办事项”列表中!:-)你有多少记性?您可能需要将结果写入磁盘。自定义客户端应用程序在R服务器池中前端处理并发请求。每个请求都在调用diffMatrix需要参与的R函数。因此,低内存和超高速是至关重要的。无论从哪个角度看,都必须计算并存储比较。除非您可以预计算这个矩阵,并存储它以供客户端稍后查找,否则您所要求的实际上是不可能的。是的,但是应该有某种方法来混合expand.grid idea()和我的半行循环方法。明天我将尝试@alexis_laz的建议。您可能可以根据矩阵包含的数据类型来选择捷径:浮点型、整数型、有限范围内的整数型、逻辑型或其他类型?它稀疏吗?
library(inline)
ff = cfunction(sig = c(R_mat = "matrix"), body = '
SEXP mat, dims, ans, dimans;
PROTECT(dims = getAttrib(R_mat, R_DimSymbol));
PROTECT(dimans = allocVector(INTSXP, 2));
R_len_t *pdims = INTEGER(dims), *pdimans = INTEGER(dimans);
PROTECT(ans = allocVector(INTSXP, pdims[0]*pdims[0]));
R_len_t *pans = INTEGER(ans);
pdimans[0] = pdims[0];
pdimans[1] = pdims[0];
for(int ina = 0; ina < LENGTH(ans); ina++) {
pans[ina] = NA_INTEGER;
}
switch(TYPEOF(R_mat)) {
case REALSXP:
{
PROTECT(mat = coerceVector(R_mat, REALSXP));
double *pmat = REAL(mat);
for(int i = 0; i < pdims[0]; i++) {
R_len_t ir;
for(ir = i+1; ir < pdims[0]; ir++) {
R_len_t diffs = 0;
for(int ic = 0; ic < pdims[1]; ic++) {
if(pmat[i + ic*pdims[0]] != pmat[ir + ic*pdims[0]]) {
diffs++;
}
}
pans[ir + i*pdims[0]] = diffs;
}
}
break;
}
case INTSXP:
{
PROTECT(mat = coerceVector(R_mat, INTSXP));
R_len_t *pmat = INTEGER(mat);
for(int i = 0; i < pdims[0]; i++) {
R_len_t ir;
for(ir = i+1; ir < pdims[0]; ir++) {
R_len_t diffs = 0;
for(int ic = 0; ic < pdims[1]; ic++) {
if(pmat[i + ic*pdims[0]] != pmat[ir + ic*pdims[0]]) {
diffs++;
}
}
pans[ir + i*pdims[0]] = diffs;
}
}
break;
}
}
setAttrib(ans, R_DimSymbol, dimans);
UNPROTECT(4);
return(ans);
')
m = matrix(c(8,4,8,4,3,2,1,1,4,5,1,2), ncol = 2)
ff(m)
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] NA NA NA NA NA NA
#[2,] 1 NA NA NA NA NA
#[3,] 1 2 NA NA NA NA
#[4,] 2 1 2 NA NA NA
#[5,] 1 1 2 2 NA NA
#[6,] 2 2 2 2 2 NA
all.equal(diffMatrix(m), ff(m))
#[1] TRUE
m2 <- matrix(sample(1:5, 50000, replace=T), ncol=10, byrow=TRUE)
library(microbenchmark)
microbenchmark(diffMatrix(m2), ff(m2), times = 10)
#Unit: milliseconds
# expr min lq median uq max neval
# diffMatrix(m2) 6972.9778 7049.3455 7427.807 7633.7581 11337.3154 10
# ff(m2) 422.3195 469.5771 530.470 661.8299 862.3092 10
all.equal(diffMatrix(m2), ff(m2))
#[1] TRUE