RcppArmadillo : for 루프의 음수 인덱싱
저는 for()Rcpp를 처음 접했고 RcppArmadillo를 사용하여 루프 에서 음수 인덱싱을 기반으로 계산을 수행하려고합니다 . 나는 이미 RcppArmadillo의 네거티브 인덱싱이 그렇게 간단하지는 않지만 유지되어야하는 요소의 벡터를 통해 수행 될 수 있다는 것을 이미 발견했습니다 (여기에서 찾은 것처럼) . 제거 할 요소가 루핑 인덱스 일 때 그것은 나에게 약간 어려운 것 같습니다. 이 답변 에서 마지막 접근 방식을 구현하려고 시도했지만 성공하지 못했습니다. 루프의 인덱스로 요소를 제외한 요소의 벡터를 지정하는 쉬운 방법이 있습니까?
따라서 y[-i]다음 MWE 에서 RcppArmadillo에서 동등한 항목을 찾으려고합니다 .
# In R:
# Input
n <- 10
y <- 1:20
# Computation
x <- rep(NA, n)
for(i in 1:n){
x[i] <- sum(y[-i])
}
지금까지 내 코드 Rcpp 코드 :
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
arma::vec rcpp_sum (arma::vec y, int n){
arma::vec x(n);
arma::vec ind(n);
for (i=0; i<n; i++){
ind[i] = /*no idea...*/
x[i] = sum(y[ind]);
}
return x;
}
어떤 도움이라도 대단히 감사합니다!
답변
이와 같은 작업의 경우 해당 색인을 건너 뛰는 것이 가장 좋습니다. 표준에서는 C++색인을 확인하고 건너 뜁니다. 이 같은:
// [[Rcpp::export]]
arma::vec rcpp_sum (arma::vec y, int n){
arma::vec x(n);
for (int i = 0; i < n; i++) {
x[i] = 0; // Initialize value
for (int j = 0; j < y.size(); ++j) {
if (i != j) {
x[i] += y[j];
}
}
}
return x;
}
위에서 우리는 설탕 구문에서 멀어지고 있습니다. IMO는 대체가 지나치게 복잡하지 않기 때문에 이와 같은 경우에 괜찮습니다. 단순화하는 동안 RcppArmadillo순수를 사용할 수 있으므로에 대한 종속성 은 필요하지 않습니다.Rcpp
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector pure_rcpp_sum (NumericVector y, int n){
NumericVector x(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < y.size(); ++j) {
if (i != j) {
x[i] += y[j];
}
}
}
return x;
}
출력 확인 :
all.equal(as.vector(rcpp_sum(y, n)), x)
[1] TRUE
all.equal(pure_rcpp_sum(y, n), x)
[1] TRUE
최신 정보
OP의 요청에 따라 R이러한 특정 목적을 위해 최적화 된 접근 방식 이 있습니다. 위의 내용은에서 하나의 값을 제외하고 벡터의 값만 합산하는 매우 구체적인 문제를 공격하는 방법을 보여줍니다 C++. 이것은 본질적으로 교육적이며이 특정 작업에 대해 반드시 가능한 최선의 방법은 아닙니다 (아래에 표시).
간단한 R코드를 보여주기 전에 내부 루프에 간단한 조건문이 있다는 OP의 우려를 C++두려워해서는 안된다는 점을 지적하고 싶습니다 (base의 경우처럼 R). 내가 알 수 있듯이 OP의 링크에서 설명한 부분 집합은 O (n)이며 추가 논리 벡터의 추가 오버 헤드가 있습니다. 위에서 제안한 솔루션은 기본적으로 추가 객체없이 동일한 작업을 수행하므로 더 효율적이어야합니다.
이제 업데이트 된 코드 :
baseR <- function(y, n) {
mySum <- sum(y)
vapply(1:n, function(x) mySum - y[x], FUN.VALUE = 1)
}
## Here is the OP code for reference
OP <- function(y, n) {
x <- rep(NA, n)
for(i in 1:n) {x[i] <- sum(y[-i])}
x
}
그게 다야. 번개처럼 빠릅니다.
huge_y <- rnorm(1e6)
huge_n <- 1e3
system.time(t1 <- baseR(huge_y, huge_n))
user system elapsed
0.003 0.000 0.003
system.time(t2 <- pure_rcpp_sum(huge_y, huge_n))
user system elapsed
2.776 0.003 2.779
system.time(t3 <- OP(huge_y, huge_n))
user system elapsed
9.555 1.248 10.805
all.equal(t1, t2)
[1] TRUE
all.equal(t1, t3)
[1] TRUE