我有一个xts格式的数据(数据)如下所示:
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类对象编制索引。我正在创建名为' 1second',' 3second'的新列。对于列' 1秒',对于每一行,我想根据他们的xts时间对象在下一个1秒内找到下一个观察并记录' A'行的值。如果在接下来的几秒内没有观察到,则将NA放在该行的数据$ 1秒内。
类似地,对于列" 3秒",对于每一行,我想根据它们的xts时间对象在接下来的3秒内找到前导观察。如果在接下来的3秒内有多个行具有相同的时间戳,则仅使用最后一个观察。
如果在接下来的3秒内没有观察,则将NA放入该行的数据$ 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]])]
}
}
}
我想知道是否可以使用Rcpp来避免使用for循环。非常感谢你的帮助。
答案 0 :(得分: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行),而不是在列上循环。然后一个&#34; left_joins&#34;这到原始数据帧。然后从时间戳中减去一秒钟,并且#34; left_joins&#34;它再次进入原始数据帧。这重复3次以考虑1秒,2秒和3秒延迟(线2-5)。现在,它是一个包含&#34;正确&#34;的数据框。同一行中的元素;它只是找到正确列的问题。正确的列是该行没有na
的最大列(第7行)。我们仍然需要设置na
在接下来的三秒内没有后续观察的行(第8行)。在这之后我们可以删除不必要的列(第9行)并完成它。
答案 1 :(得分:1)
如果您需要Rcpp解决方案,可以使用
@extend
然后,在获取此.cpp文件后,您只需要调用
#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;
}
请注意,您的第(n-2)行有3秒的无效性。