我用R写了一段代码,用于计算所谓的排名统计信息的双倍和。
我需要重复 Q 最小计算 1000 次,但里面有 3 个循环,只做一次需要很长时间。
这是我的代码:
#u, a - real numbers
l <- function(u, a) {
-sqrt((1-a)/a)*I(u>=0 & u<a) + sqrt(a/(1-a))*I(u>=a & u<=1)
}
# r,s - real number, R,S - vectors of real numbers (equal lengths)
L<-function(r, s, R, S) {
n<-length(R)
x<-0
for (i in 1:n) {
x<-x+l(R[i]/(n+1),r) * l(S[i]/(n+1),s)
}
1/sqrt(n)*x
}
# r, s, X, Y - vectors of real numbers; X and Y must be equally long
Q<-function(r,s,X,Y) {
n<-length(X)
R<-rank(X)
S<-rank(Y)
q<-0
for (j in 1:length(r)) {
for (k in 1:length(s)) {
q<-q+L(r[j],s[k],R,S)^2
}
}
q
}
我尝试使用 sapply 和 apply 转换我的函数,但随后第一个函数失败了,因为 r 和 s 的大小可能不相等(r、s 的长度也不应该等于 X(或 Y)的长度)。
有没有办法产生一个函数 L,它接受 4 个向量并生成一个矩阵,以便我摆脱循环?
提前感谢!
//编辑:
我使用 mapply 编写了一个替代函数:
Q1<-function(r,s,X,Y) {
n<-length(X)
R<-rank(X)
S<-rank(Y)
rs <- expand.grid(r,s)
q<-do.call(mapply, c(function(r,s) L(r,s,R=R,S=S)^2, unname(rs)))
sum(q)
}
但它似乎更慢。
如果要为r
和s
的不同值生成L(.)的所有值,则无循环方法可能是:
rs <- expand.grid(r=r,s=s); rm(r); rm(s)
#edit
rs$qrs <- with(rs, L(r, s, R, S)^2 )
q <- sum(rs$qrs)
我不相信这会更快。有一个普遍但错误的概念,即R中的循环效率低下。效率的大部分收益将来自简化内部功能。
> set.seed(123)
> r <- runif(4)
> s <- runif(3)
> rs <- expand.grid(r=r,s=s)
> rs
r s
1 0.2875775 0.9404673
2 0.7883051 0.9404673
3 0.4089769 0.9404673
4 0.8830174 0.9404673
5 0.2875775 0.0455565
6 0.7883051 0.0455565
7 0.4089769 0.0455565
8 0.8830174 0.0455565
9 0.2875775 0.5281055
10 0.7883051 0.5281055
11 0.4089769 0.5281055
12 0.8830174 0.5281055
> rs$qrs <- with(rs, L(r, s, 1:10, 1:10)^2 )
> q <- sum(rs$qrs)
> q
[1] 14.39009
> rs
r s qrs
1 0.2875775 0.9404673 0.0004767998
2 0.7883051 0.9404673 0.0003911883
3 0.4089769 0.9404673 6.6571168565
4 0.8830174 0.9404673 0.0017673788
5 0.2875775 0.0455565 0.0004767998
6 0.7883051 0.0455565 0.0003911883
7 0.4089769 0.0455565 6.6571168565
8 0.8830174 0.0455565 0.0017673788
9 0.2875775 0.5281055 0.0004767998
10 0.7883051 0.5281055 0.0003911883
11 0.4089769 0.5281055 6.6571168565
12 0.8830174 0.5281055 0.0017673788