11

これは、data.frame の一部として持っているブール値のサンプルです。

atest <- c(FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE)

各 FALSE から 1 から始まり、次の FALSE まで 1 ずつ増加する一連の数値を返したいと考えています。

結果の目的のベクトルは次のとおりです。

[1]  1  2  3  4  5  6  7  8  9 10  1  2  3  4  5  6  7  8  9 10  1

これを実現するコードは次のとおりですが、R でこれを行うには、もっと簡単で洗練された方法があると確信しています。単に仕事を終わらせるのではなく、R でより効率的にコーディングする方法を常に学ぼうとしています。

result <- c()
x <- 1
for(i in 1:length(atest)){
    if(atest[i] == FALSE){
        result[i] <- 1
        x <- 1
    } 
    if(atest[i] != FALSE){
        x <- x+1
         result[i] <- x
    }
}
4

3 に答える 3

2

このような問題は、 でうまく機能する傾向がありRcppます。@flodel のコードをベンチマークのフレームワークとして借りて、

boolseq.cpp
-----------

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
IntegerVector boolSeq(LogicalVector x) {
  int n = x.length();
  IntegerVector output = no_init(n);
  int counter = 1;
  for (int i=0; i < n; ++i) {
    if (!x[i]) {
      counter = 1;
    }
    output[i] = counter;
    ++counter;
  }
  return output;
}

/*** R
x <- c(FALSE, sample( c(FALSE, TRUE), 1E5, TRUE ))

f0 <- function(x) sequence(tabulate(cumsum(!x)))
f1 <- function(x) {i <- seq_along(x); i - cummax(i * !x) + 1L}

library(microbenchmark)
microbenchmark(f0(x), f1(x), boolSeq(x), times=100)

stopifnot(identical(f0(x), f1(x)))
stopifnot(identical(f1(x), boolSeq(x)))
*/

sourceCppそれは私に与えます:

Unit: microseconds
       expr       min        lq     median         uq       max neval
      f0(x) 18174.348 22163.383 24109.5820 29668.1150 78144.411   100
      f1(x)  1498.871  1603.552  2251.3610  2392.1670  2682.078   100
 boolSeq(x)   388.288   426.034   518.2875   571.4235   699.710   100

エレガントではありませんが、Rコードで書いていたものにかなり近いです。

于 2013-09-06T08:46:26.043 に答える