I have a symmetric matrix of probabilities with diagonal entries null. Suppose something like
0 0.5 0.1 0.6
0.5 0 0.2 0.1
0.1 0.2 0 0.2
0.6 0.1 0.2 0
I want to draw a dummy matrix so that the probability of the entry [i,j] be the entry [i,j] in the probabilities matrix. Note that the probabilities matrix I have is an Armadillo matrix (a big matrix 5000x5000). of course, the diagonal dummies should be null because their probabilities are null. I built two functions to do that but they are not fast. I should sample this matrix many times in loops.
mat binom1(mat& prob){
int n=prob.n_rows;
mat sample(n,n,fill::zeros);
NumericVector temp(2);
for(int i(0);i<n-1;++i){
for(int j(i+1);j<n;++j){
temp=rbinom(2,1,prob(i,j));
sample(i,j)=temp(0); sample(j,i)=temp(1);
}
}
return sample;
}
mat binom2(mat& prob){
int n=prob.n_rows;
mat sample(n,n);
for(int i(0);i<n;++i){
for(int j(0);j<n;++j){
sample(i,j)=as<double>(rbinom(1,1,prob(i,j)));
}
}
return sample;
}
The both are slower than vectorized rbinom in R.
z=matrix(runif(1000^2),1000) #just an example for 1000x1000 matrix
microbenchmark(rbinom(nrow(z)^2,1,z),binom1(z),binom2(z))
Results
expr min lq mean median uq max
rbinom(nrow(z)^2, 1, z) 95.43756 95.94606 98.29283 97.5273 100.3040 108.2293
binom1(z) 131.33937 133.25487 139.75683 136.4530 139.5511 229.0484
binom2(z) 168.38226 172.60000 177.95935 175.6447 180.9531 277.3501
Is there a way to make the code faster ?
I see one example here. But in my case the probabilities are in Armadillo matrix