我有一个纵向记录的变量(变量1)。我想随着时间的推移计算累计平均值(或“正常”)变量。更重要的是,我只想在Var.1满足条件时更新累计平均值,在这种情况下,它是前一个法线的70%以上。如果满足,则应进行更新;否则,应将先前的值结转。我一直在寻找矢量化解决方案,但不确定是否可行。
我的示例数据如下。我已经输入了排除第五项(50)后的正常值,因为它不满足> 70%的规则。
library(tibble)
Sample.GT = tibble(Var.1 = c(80, 80,90,90,50,80,70, 80,80,80),
Normal = c(80, 80,83.33,85,85,84,81.67,81.43,81.25,81.11))
最好使用Dplyr或data.table解决方案。我希望通过大数据集的组来实现此目标,因此快速解决方案是理想的选择。
答案 0 :(得分:1)
data.table
中可能的递归方法:
n <- 1
cs <- GT$Var.1[1L]
GT[1L, cm := cs]
GT[-1L, cm := {
if (Var.1 > 0.7*cs/n) {
cs <- cs + Var.1
n <- n + 1
}
cs / n
}, seq_len(GT[,.N])[-1L]]
或使用Rcpp
会更快:
library(Rcpp)
calcNorm <- cppFunction('
NumericVector calcNorm(NumericVector v) {
int sz = v.size();
double n = 1.0, cs = v[0];
NumericVector ret(sz);
ret[0] = cs;
for (int i = 1; i < sz; i++) {
if (v[i] > 0.7*cs/n) {
cs = cs + v[i];
n = n + 1.0;
}
ret[i] = cs / n;
}
return(ret);
}
')
GT[, newNormal := calcNorm(Var.1)]
输出:
Var.1 Normal cm
1: 80 80.00 80.00000
2: 80 80.00 80.00000
3: 90 83.33 83.33333
4: 90 85.00 85.00000
5: 50 85.00 85.00000
6: 80 84.00 84.00000
7: 70 81.67 81.66667
8: 80 81.43 81.42857
9: 80 81.25 81.25000
10: 80 81.11 81.11111
数据:
library(data.table)
GT = data.table(Var.1 = c(80, 80,90,90,50,80,70, 80,80,80),
Normal = c(80, 80,83.33,85,85,84,81.67,81.43,81.25,81.11))
编辑感谢sindri_baldur的评论