2012-06-26 3 views
3

Rcpp에는 코드에서 멋진 벡터화 연산을 허용하는 다양한 "Rcpp 설탕"명령이 있습니다. 아래의 코드에서 데이터 프레임을 가로 질러 벡터로 나누고 "ifelse"및 "sum"설탕 명령을 사용하여 x가 y 또는 y + 1 인 행에 대해 v의 평균을 계산합니다. 모두 제대로 작동하는 것 같습니다.Rcpp의 효율적인 하위 집합 (R "which 명령"과 동일)

이보다 더 깔끔한 방법이 있는지 궁금해합니다. 특정 조건을 만족하는 인덱스 포인트를 제공하는 "which"명령과 동등한가? 아르마딜로에서 "찾기"기능을 사용할 수있는 것 같지만 호환되지 않는 개체 유형을 사용한다는 의미입니다 ("찾기"와 "ifelse"를 함께 사용할 수 없음).

같은 주제에 대해 은 "ifelse"가 복합 논리 조건을 허용 할 수 있습니까? 아래 예에서, 예를 들어, indic의 정의는 두 개의 "ifelse"명령으로 이루어지며, 분명히 하나 인 것처럼 더 깨끗합니다. 어떤 생각이라도 대단히 감사 할 것입니다. |

는 답변 :

require(Rcpp) 
require(inline) 

set.seed(42) 
df = data.frame(x = rpois(1000,3), y = rpois(1000,3), v = rnorm(1000), 
       stringsAsFactors=FALSE) 

myfunc1 = cxxfunction(
    signature(DF = "data.frame"), 
    plugin = "Rcpp", 
    body = ' 
      using namespace Rcpp; 
      DataFrame df(DF); 
      IntegerVector x = df["x"]; 
      IntegerVector y = df["y"]; 
      NumericVector v = df["v"]; 

      LogicalVector indic = ifelse(x==y,true,ifelse(x==y+1,true,false)); 
      double subsum = sum(ifelse(indic,v,0)); 
      int subsize = sum(indic); 
      double mn = ((subsize>0) ? subsum/subsize : 0.0); 

      return(Rcpp::List::create(_["subsize"] = subsize, 
             _["submean"] = mn 
            )); 
      ' 
      ) 

myfunc1(df) 

### OUTPUT: 
# 
# $subsize 
# [1] 300 
# 
# $submean 
# [1] 0.1091555 
# 
+2

'Rcpp 설탕'에는 많은 것들이 있지만, 모든 것을 가지고 있지는 않습니다. 누군가는'which()'변종을 만들어야합니다. 패치 환영합니다. –

+0

당연히 ... 그리고 그것이 가지고있는 것이 훌륭합니다. 내가 말했듯이 RcppArmadillo가 올바른 일을하는 것처럼 보이는 '찾기'가 있지만, 위의 "double ifelse"접근법이 끔찍한 실수인지 아니면 지금 당장 최고의 설탕 해킹인지는 궁금합니다. –

답변

3

Rcpp (> = 0.10.0)가 를 구현을 기다리겠습니다 두 논리 설탕 표현 사이의 연산자. 그래야 할 일은 다음과 같습니다.

require(Rcpp) 

cppFunction(code = ' 
List subsum(IntegerVector x, IntegerVector y, NumericVector v){ 
    using namespace Rcpp ; 

    LogicalVector indic = (x==y) | (x==y+1) ; 
    int subsize   = sum(indic) ; 
    double submean  = subsize == 0 ? 0.0 : sum(ifelse(indic,v,0))/subsize ; 

    return List::create(_["subsize"] = subsize, _["submean"] = submean) ; 
} 
') 
subsum(rpois(1000,3), rpois(1000,3), rnorm(1000)) 
# $subsize 
# [1] 320 
# 
# $submean 
# [1] -0.05708866