使用“combn”和“outer”功能的组合提高运算速度

我有一个数据框 df ,其中包含两个变量,如下所示。使用下面的代码,我想获得矩阵“mat”。

此代码适用于 unique(df$V1)= 3 但对于 unique(df$V1) 为 1000 的操作需要大量时间(> 10 小时)。

数据框

V1   V2
1   60
1   30
1   38
1   46
2   29
2   35
2   13
2   82
3   100
3   72
3   63
3   45

代码:

#Unique V1 values
vec <- unique(df$V1)
#Count <= valies
val <- combn(vec, 2, function(x) 
  sum(outer(df$V2[df$V1 == x[1]], df$V2[df$V1 == x[2]], `<=`)))
val
#[1]  5 14 13

#Create an empty matrix
mat <- matrix(0,length(vec), length(vec))
#Fill the lower triangle of the matrix. 
mat[lower.tri(mat)] <- val
mat

基本上,对于 V1=1,我们希望将 V2 的所有值与 V1=2 和 3 的 V2 的所有值进行比较。对 V1=2 和 V1=3 重复相同的操作。换句话说,对于给定的 V1 值,我们想查看 V2 中的值是否小于 V1 中其余值的 V2 中的值。例如,我们比较 V2 中 V1=1 和 V1=2 的值。如果 V1=1 时 V2 中的值小于 V1=2 时 V2 中的值,则返回值为 1 否则为 0。例如:

For V1=1->
( 60 > 29 : returns 0,
60 > 35 : returns 0,
60 > 13 : returns 0,
60 < 82 : returns 1,
30 > 29 : returns 0,
30 < 35 : returns 1,
30 > 13 : returns 0,
30 < 82 : returns 1,
38 > 29 : returns 0,
38 > 35 : returns 0,
38 > 13 : returns 0,
38 < 82 : returns 1,
46 > 29 : returns 0,
46 > 35 : returns 0,
46 > 13 : returns 0,
30 < 82 : returns 1)=Sum is 5 (i.e. mat[1,2])

回答

对于这个问题,这应该是闪电般的快速,而不是使用过多的内存。

library(data.table)
setDT(df)
numvec <- max(df[,V1])
dl <- lapply(1:numvec, function(i) df[V1 == i, sort(V2)])
dmat <- CJ(x=1:numvec, y=1:numvec)[, .(z = sum(findInterval(dl[[y]],dl[[x]]))), .(x,y)]
mat <- as.matrix(dcast(dmat, x~y, value.var = 'z')[, -'x'])


以上是使用“combn”和“outer”功能的组合提高运算速度的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>