which(x,arr.ind=T)
Rcpp や RcppArmadillo にはクールな機能が見つかりませんでした。それで、私はすぐにそれを自分でコーディングすることにしました。
// [[Rcpp::export]]
arma::umat whicha(arma::mat matrix, int what ){
arma::uvec outp1;
int n = matrix.n_rows;
outp1 = find(matrix==what);
int nf = outp1.n_elem;
arma::mat out(nf,2);
arma::vec foo;
arma::uvec foo2;
foo = arma::conv_to<arma::colvec>::from(outp1) +1;
foo2 = arma::conv_to<arma::uvec>::from(foo);
for(int i=0; i<nf; i++){
out(i,0) = ( foo2(i) %n);
out(i,1) = ceil(foo(i) / n );
if(out(i,0)==0) {
out(i,0)=n;
}
}
return(arma::conv_to<arma::umat>::from(out));
}
このコードは非常に効率が悪いように見えますが、R の関数microbenchmark
よりも高速であることがわかります。which
質問: この関数をさらに変更して、R のwhich
関数を実際に正確に再現する、つまり渡すMATRIX == something
ことはできますか? 今のところ、そのための2番目の引数が必要です。利便性のためにこれを持っているだけです。
更新: バグを修正しました - 床の代わりに天井が必要でした
確認方法:
ma=floor(abs(rnorm(100,0,6)))
testf=function(k) {all(which(ma==k,arr.ind=T) == whicha(ma,k))} ; sapply(1:10,testf)
基準:
> microbenchmark(which(ma==k,arr.ind=T) , whicha(ma,k))
Unit: microseconds
expr min lq median uq max neval
which(ma == k, arr.ind = T) 10.264 11.170 11.774 12.377 51.317 100
whicha(ma, k) 3.623 4.227 4.830 5.133 36.224 100