2017-10-10 144 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秒。