想象一下像
这样的一系列数字c(21,22,23,30,31,32,34,35,36,37,38,50,NA,52)
子系列定义为:x[t]
是x[t] = x[t-1] + 1
的某个子系列的一部分吗?
所以在上面的例子中我们有以下系列:
c(21,22,23,30,31,32,34,35,36,37,38,50,NA,52)
## 1 1 1 2 2 2 3 3 3 3 3 4 - 5 # serie ID
## 3 | 3 | 5 | 1 | | 1 # length
标记子系列并计算其长度的最有效方法是什么(作为单个函数或两个单独的函数)?
答案 0 :(得分:3)
我们可以得到相邻元素之间的差异,检查它是否等于1,得到累积和,并将其用作组来获得向量的长度
unname(tapply(v1, cumsum(c(TRUE, diff(replace(v1, is.na(v1), 0))!=1)), length))
#[1] 3 3 5 1 1 1
如果我们需要NA
元素作为""
unname(tapply(v1, cumsum(c(TRUE, diff(replace(v1, is.na(v1), 0))!=1)),
function(x) if(all(is.na(x))) "" else length(x)))
#[1] "3" "3" "5" "1" "" "1"
@DavidArenburg与rle
rle(cumsum(c(TRUE, diff(replace(v1, is.na(v1), 0))!=1)))$lengths
答案 1 :(得分:1)
我接受 akrun 的回答(由 David Arenburg 提供),但为了参考,我提供了一个 Rcpp 解决方案我在此期间创造。
NumericVector cpp_seriesLengths(NumericVector x) {
int n = x.length();
if (n == 1)
return wrap(1);
NumericVector out(n);
int tmpCount = 1;
int prevStart = 0;
for (int i = 0; i < (n-1); i++) {
if ( x[i] == (x[i+1] - 1) ) {
tmpCount += 1;
} else {
for (int j = prevStart; j <= i; j++)
out[j] = tmpCount;
tmpCount = 1;
prevStart = i+1;
}
}
for (int j = prevStart; j < n; j++)
out[j] = tmpCount;
return out;
}