2017-10-10 4 views
2

でループに使用して回避するRcppを使用する方法を次のようになります任意の列または行の要素にはパターンが存在しない私はXTSフォーマットデータ(データ)を有するR

       A 
2008-01-14 09:29:59   10 
2008-01-14 09:29:59   0.1 
2008-01-14 09:30:00   0.9 
2008-01-14 09:30:00   0.1 
2008-01-14 09:30:00   0.2 
2008-01-14 09:30:00   0.4 
2008-01-14 09:30:00   0.6 
2008-01-14 09:30:00   0.7 
2008-01-14 09:30:02   1.5 
2008-01-14 09:30:06   0.1 
2008-01-14 09:30:06   0.1 
2008-01-14 09:30:07   0.9 
2008-01-14 09:30:07   0.2 
2008-01-14 09:30:10   0.4 
2008-01-14 09:30:10   0.3 
2008-01-14 09:30:25   1.5 

データは、POSIXctクラスオブジェクトによって索引付けされます。私は「1秒」、「3秒」という新しい列を作成しています。列「1秒」に対して、各行について、そのxts時間オブジェクトに従って次の1秒以内に次の観測を探し、その行の「A」値を記録したい。次の秒以内に観測がなければ、その行の$ 1秒のデータにNAを入れます。

同様に、「3秒」の列については、各行について、そのxts時間オブジェクトに従って次の3秒以内に先頭の観測を探したいと思います。次の3秒以内に同じタイムスタンプを持つ複数の行がある場合は、最後の観測のみを使用します。

次の3秒以内に何も観察されない場合は、その行に$ 3秒のデータを入れます。 は例えば、私は次のような結果を期待する:

       B 1second 3second 
2008-01-14 09:29:59   10 0.7  1.5   
2008-01-14 09:29:59   0.1 0.7  1.5 
2008-01-14 09:30:00   0.9 NA  1.5 
2008-01-14 09:30:00   0.1 NA  1.5 
2008-01-14 09:30:00   0.2 NA  1.5 
2008-01-14 09:30:00   0.4 NA  1.5 
2008-01-14 09:30:00   0.6 NA  1.5 
2008-01-14 09:30:00   0.7 NA  1.5 
2008-01-14 09:30:02   1.5 NA  NA 
2008-01-14 09:30:06   0.1 0.2  0.2 
2008-01-14 09:30:06   0.1 0.2  0.2 
2008-01-14 09:30:07   0.9 NA  0.3 
2008-01-14 09:30:07   0.2 NA  0.3 
2008-01-14 09:30:10   0.4 NA  0.3 
2008-01-14 09:30:10   0.3 NA  NA 
2008-01-14 09:30:25   1.5 NA  NA 

ここに私の現在のコードがあり、それは動作しますが、非常に遅いです。

TimeStmp is the POSIXct object. 
     TimeHorizon<-c(1,3) 
     for(j in 1:nrow(data)){ 
     a<-sapply(TimeHorizon,function(x) which(TimeStmp==TimeStmp[j] +x)) 
     for(k in 1:length(a)){ 
      if (length(a[[k]]>0)){ 
      data[j,k+1]<-(data$B)[last(a[[k]])] 
      } 
     } 
     } 

forループを使用しないようにRcppを使用できるかどうかは疑問です。助けてくれてありがとう。

+0

[競争指標を計算するループを回避する方法](https://stackoverflow.com/questions/42020341/how-to-avoid-a-loop-to-calculate-competition-index) – Mateusz1981

答えて

1

コードを持つすべてあまりにも満足していないが、それは一つのアプローチであるかもしれない:

temp1 <- test[! duplicated(test$timestamp, fromLast = T), ] 
for (i in c(0,rep(1,3))) { 
    temp1$timestamp <- temp1$timestamp - i 
    test <- merge(test, temp1, by = "timestamp", all.x = T) 
} 
colnames(test) <- c("timestamp", "B", "0second", "1second", "2second", "3second") 
test$`3second` <- test[-1][cbind(1:nrow(test), max.col(!is.na(test[-1]), "last"))] 
test$`3second`[shift(test$timestamp,1,type = "lead") - test$timestamp > 3 | is.na(shift(test$timestamp,1,type = "lead") - test$timestamp)] <- NA 
test <- test[c("timestamp", "B", "1second", "3second")] 
test 
#    timestamp B 1second 3second 
# 1 2008-01-14 09:29:59 0.1  0.7  1.5 
# 2 2008-01-14 09:29:59 10.0  0.7  1.5 
# 3 2008-01-14 09:30:00 0.9  NA  1.5 
# 4 2008-01-14 09:30:00 0.1  NA  1.5 
# 5 2008-01-14 09:30:00 0.2  NA  1.5 
# 6 2008-01-14 09:30:00 0.4  NA  1.5 
# 7 2008-01-14 09:30:00 0.6  NA  1.5 
# 8 2008-01-14 09:30:00 0.7  NA  1.5 
# 9 2008-01-14 09:30:02 1.5  NA  NA 
# 10 2008-01-14 09:30:06 0.1  0.2  0.2 
# 11 2008-01-14 09:30:06 0.1  0.2  0.2 
# 12 2008-01-14 09:30:07 0.9  NA  0.3 
# 13 2008-01-14 09:30:07 0.2  NA  0.3 
# 14 2008-01-14 09:30:10 0.3  NA  0.3 
# 15 2008-01-14 09:30:10 0.4  NA  NA 
# 16 2008-01-14 09:30:25 1.5  NA  NA 

編集:ちょうどあなたがRcppを使用することを見ました。さて、この答えを無視してください。 :)

EDIT2:私のコードに説明します。説明が最善でない場合は私の言い訳です。 列をループするのではなく、最初に各タイムスタンプの最後の観測値を取得します(1行目)。次に、元のデータフレームに「left_join」します。その後、タイムスタンプから1秒が減算され、元のデータフレームに再度left-joinされます。これは、1秒、2秒、および3秒の遅延を説明するために3回繰り返されます(2〜5行目)。今、それは同じ行に "正しい"要素を含むデータフレームです。それは正しい列を見つけることの唯一の問題です。正しい列は、その行(行7)に対してnaを持たない最大の列です。私たちはまだnaに、次の3秒(8行目)でフォローアップ観測を持たない行を設定する必要があります。これを実行した後、不要な列を削除することができます(行9)。

+0

コード回答のみが、質問の問題をどのように解決するか説明していないため、お勧めできません。あなたの答えを更新して、これが何をし、どのように問題を解決するのかを説明してください。 [よくある回答を書くにはどうすればいいですか](https://stackoverflow.com/help/how-to-answer) – FluffyKitten

1

あなたが次に

#include <Rcpp.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
NumericVector name_me(List df, double nsec) { 

    NumericVector TimeStmp = df["TimeStmp"]; 
    NumericVector B  = df["B"]; 
    int n = B.size(); 
    int i, j, k, ndup; 
    double time; 

    NumericVector res(n); 

    for (i = 0; i < n; i++) { 

    // get last for same second 
    for (ndup = 0; (i+1) < n; i++, ndup++) { 
     if (TimeStmp[i+1] != TimeStmp[i]) break; 
    } 

    // get last value within nsec 
    time = TimeStmp[i] + nsec; 
    for (j = i+1; j < n; j++) { 
     if (TimeStmp[j] > time) break; 
    } 

    // fill all previous ones with same value 
    res[i] = (j == (i+1)) ? NA_REAL : B[j-1]; 
    for (k = 1; k <= ndup; k++) res[i-k] = res[i]; 
    } 

    return res; 
} 

を使用することができますRcppソリューションをしたい場合は、この.cppファイルを調達した後、あなただけの

name_me(df, 1) 
name_me(df, 3) 

を呼び出す必要がinconstitencyは、あなたの中に存在することに注意してください( n-2)行目に3秒間表示する。

関連する問題