2012-06-26 1 views
3

В Rcpp существуют различные команды «Rcpp sugar», которые допускают красивые векторизованные операции в коде. В приведенном ниже коде я перемещаюсь по кадру данных, разбиваю его на векторы, а затем использую команды «ifelse» и «sum» sugar для вычисления среднего значения v по строкам, где x равно y или y + 1. Кажется, все работает правильно.Эффективное подмножество в Rcpp (эквивалентно команде R ", которая")

Просто интересно, есть ли более чистый способ, чем это - например. эквивалент команды «which», которая дает индексные точки, удовлетворяющие определенному условию? В Armadillo есть средство, доступное как «найти», но это означает использование несовместимых типов объектов (вы не можете использовать «find» и «ifelse» вместе).

На эту же тему, можно ли получить «ifelse», чтобы принять составное логическое условие? В приведенном ниже примере, например, определение знака формируется из двух команд 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 sugar» имеет много тонкостей, но в нем нет всего. Кому-то нужно приготовить вариант 'which()', я полагаю. Патчи приветствуются. –

+0

Конечно ... и то, что у него есть, замечательно. Как я уже сказал, есть RcppArmadillo 'find', который, кажется, поступает правильно, но мне было просто любопытно, является ли подход« 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 
Смежные вопросы