2017-10-10 116 views
2

使用循環我有一個XTS格式的數據(數據)是這樣的:如何使用RCPP避免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秒'的新列。對於'1second'列,我想根據它們的xts時間對象在下一個1秒內找到下一個觀測值並記錄該行的'A'值。如果在接下來的秒內沒有觀察到,則在該行中將NA放置在數據$ 1秒內。

同樣,對於列「3秒」,對於每一行,我想根據它們的xts時間對象在接下來的3秒內找到前導觀察值。如果在接下來的3秒內有多個具有相同時間標記的行,則僅使用最後一次觀察。

如果在接下來的3秒內沒有觀察到,則在該行的數據$ 3秒內放置NA。 例如,我希望下面的結果:

       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]])] 
      } 
     } 
     } 

我想知道是否可以使用Rcpp避免使用for循環。十分感謝你的幫助。

+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。那麼就忽略這個答案吧。 :)

編輯2:解釋我的代碼。對不起,如果解釋不是最好的: 而不是循環的列,首先得到每個時間戳的最後一次觀察(第1行)。然後一個「left_joins」到原始數據幀上。之後,從時間戳中減去一秒,然後再將其「left_joins」到原始數據幀中。這重複了3次以解釋1秒,2秒和3秒延遲(第2-5行)。現在,它是一個數據框,它包含同一行中的「正確」元素;這只是找到正確列的問題。正確的列是該行(行7)沒有na的最大列。我們仍然需要設置na在接下來的三秒內沒有跟蹤觀察的行(第8行)。這樣做後,我們可以刪除不必要的列(第9行),並完成。

+0

代碼因爲他們沒有解釋他們如何解決問題中的問題,所以只有答案是不鼓勵的。考慮更新你的答案,以解釋這是什麼以及它如何解決這個問題。請回顧[我如何寫出一個好的答案](https://stackoverflow.com/help/how-to-answer) – FluffyKitten

1

如果你想要一個RCPP解決方案,您可以使用

#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; 
} 

然後,採購此.cpp文件後,你只需要調用

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

注意,有在inconstitency你( n-2)行3秒。