我有一个矩阵z(3 x 20000)。将每一行视为随机变量,将每列视为一个模拟。我使用apply命令在R中编写了以下函数,以便在3维中找到经验累积分布函数(EMP.CDF)。这个k变量经验CDF在this pdf的第2页,“多变量ECDF”一节中进行了解释。
EMP.CDF=function(z) {
# z is a matrix (3 x 20000) and each row is a realization of a random variable
q1=z[1,];q2=z[2,];q3=z[3,]
# qi = the realization of the ith random variable, i=1,2,3
# Now I am going to evaluate the empirical cumulative distribution function at
# each column of z
# Given each column, the function should return an empirical
# cumulative probability.
d=apply(z,2, function(x) sum(q1<=x[1] & q2<=x[2] & q3<=x[3])/(length(q1)))
return(d)}
> z=matrix(0,3,20000)
> z[1,]=runif(20000,1,2)
> z[2,]=runif(20000,3,5)
> z[3,]=runif(20000,7,9)
> system.time(EMP.CDF(z))
user system elapsed
30.18 0.01 30.39
在上面的代码中k = 3。有什么方法可以矢量化上面的函数来减少系统时间吗?
答案 0 :(得分:1)
三维累积分布函数是3个变量的函数。 如果你在网格上估计它,它可以表示为一个三维数组, 但它会是不精确和巨大的(你的函数返回一维数组, 所以它不是计算机。)
给定一个点x
,只需计算所有坐标均小于x
的点的比例。
z <- matrix(runif(60000), 3, 20000)
emp.cdf <- function(z)
function(x) mean( apply( z <= x, 2, all ) )
emp.cdf(z)( c(.5,.5,.5) ) # Approximately 1/8
以下内容将再现您引用的文档中的图:
n <- 10
z <- matrix(runif(2*n), 2, n)
f <- emp.cdf(z)
g <- function(u,v) f(c(u,v))
persp( outer( sort(z[1,]), sort(z[2,]), Vectorize(g) ) )
x <- seq(0,1,length=100)
persp( outer( x, x, Vectorize(g) ) )
如果要评估初始点的累积概率分布,
您可以使用apply
(如果您想在网格上对其进行评估,可以使用expand.grid
进行构建)。
n <- 100
z <- matrix(runif(3*n), 3, n)
f <- emp.cdf(z)
p <- apply( z, 2, f )
但是这个算法是二次的:要计算n
个概率,
对于每一个,我们检查所有3*n
坐标。
对于你的20,000点,这需要一段时间。
您可以使用分而治之的方法 加快计算速度, 但这并不简单: 随意拿起一点, 用它将空间分成8个八分圆, 递归地计算每个八分圆中的点数; 然后,您可以使用生成的tree 计算任何点的概率, 只检查一小部分。
这与预处理步骤没有什么不同 用于计算k-nearest neighbours, 或加快n-body simulations。