我想优化我的r函数来计算基尼误差:
gini.md<- function(x)
{
n = length(x)
nm = n+1
x = sort(x)
return (2/n^2*sum((2*(1:n)-nm)*x))
}
你知道如何让它更快吗?用seq生成seqences很慢。 bitwShiftL((1:n), 1)
比2* (1:n)
慢。怎么可能?
此外,我发现mean(x)
比sum(x)/length(x)
慢。再次为什么???均值是一个内部函数它应该更快。
答案 0 :(得分:1)
忽略了我自己的建议,我猜测任何速度问题的最可能的来源是不必要地创建长向量。以下C实现避免了创建四个向量(1:n
,2 * (1:n)
,2 * (1:n) - nm
,最后是(2*(1:n)-nm)*x
)。
library(inline)
gini <- cfunction(signature(x="REALSXP"), "
double n = Rf_length(x), nm = n + 1, ans = 0;
const double *xp = REAL(x);
for (int i = 0; i < n; ++i)
ans += (2 * (i + 1) - nm) * xp[i];
return ScalarReal(2 * ans / (n * n));
")
但这似乎没什么帮助。我意识到评估时间由sort()
支配。
> library(microbenchmark)
> x <- rnorm(100000)
> all.equal(gini.md(x), gini(sort(x)))
[1] TRUE
> microbenchmark(gini.md(x), gini(sort(x)), sort(x), times=10)
Unit: milliseconds
expr min lq mean median uq max neval
gini.md(x) 10.668591 10.98063 11.09274 11.03377 11.20588 11.62714 10
gini(sort(x)) 10.439458 10.64972 10.78242 10.70099 10.93015 11.36177 10
sort(x) 9.995886 10.18180 10.31508 10.27024 10.46160 10.66006 10
也许有更多的速度,但它也同样是边缘的。