【发布时间】:2014-11-29 17:07:13
【问题描述】:
我在 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)
}
但它似乎更慢。
【问题讨论】:
-
使用
L(r[j],s[k],R,S)^2可能比调用 L 函数两次来做:L(r[j],s[k],R,S)*L(r[j],s[k],R,S)更快。预维向量并分配到位置也比连接更快。 -
嗯,确实 - 使用 ^2 而不是乘法有帮助,它现在快了近 2 倍,非常感谢。我还在这两个函数中用累积求和替换了串联,它节省了大约。 0.1 秒。不过,仍然想知道是否有办法省略循环(前提是确实需要更少的时间)。
-
不确定您是否理解了预先维度的建议。你应该编辑你的代码来显示你做了什么。
-
我想我做到了(你的意思是声明指定长度的向量,然后用值填充它们,不是吗?)但我只是尝试了一些我认为会更快的方法(也许我错了)。我编辑了我的代码。
标签: r sum vectorization apply sapply