这是我的代码: 第1步:定义一个我将在稍后使用的反函数
inverse = function (f, lower = -100, upper = 100) {
function (y) uniroot((function (x) f(x) - y), lower = lower, upper = upper)[1]
}
Step2:这是我的函数及其反函数:
F1<-function(x,m1,l,s1,s2){l*pnorm((x-m1)/s1)+(1-l)*pnorm((x+m1)/s2)}
F1_inverse = inverse(function(x) F1(x,1,0.1,2,1) , -100, 100)
F2<-function(x,m2,l,s1,s2){l*pnorm((x-m2)/s1)+(1-l)*pnorm((x+m2)/s2)}
F2_inverse = inverse(function(x) F1(x,1,0.1,2,1) , -100, 100)
Step3:这是我的最终功能,它结合了上述功能(我确信功能正确):
copwnorm<-function(x,y,l,mu1,mu2,sd1,sd2) {
(l*dnorm(((F1_inverse(pnorm(x))$root-mu1)/sd1))*
dnorm(((F2_inverse(pnorm(y))$root-mu2)/sd1)))
}
步骤4:我想在步骤enter code here
3中为函数创建等高线图:
x<-seq(-2,2,0.1)
y<-seq(-2,2,0.1)
z<-outer(x,y,copwnorm)
contour(x,y,z,xlab="x",ylab="y",nlevels=15)
问题出现了,当我尝试应用函数outer(x,y,copwnorm)时,它给出了一个错误:'zeroin'中的函数值无效。请问如何解决这个问题?
答案 0 :(得分:5)
我认为假设outer(x, y, FUN)
为每个必需的对FUN
和x[i]
调用函数参数(y[j]
),这是一个非常普遍的误解。实际上,outer
在创建所有可能的对后,将FUN
仅调用一次,将x
的每个元素与y
的每个元素组合在一起方式类似于函数expand.grid
。
我将通过一个例子来说明:考虑这个函数,它是产品的包装器,每次调用时都会打印一条消息:
f <- function(x,y)
{
cat("f called with arguments: x =", capture.output(dput(x)), "y =", capture.output(dput(y)), "\n")
x*y
}
此函数是“自然”矢量化的,因此我们可以使用矢量参数调用它:
> f(c(1,2), c(3,4))
f called with arguments: x = c(1, 2) y = c(3, 4)
[1] 3 8
使用outer
:
> outer(c(1,2), c(3,4), f)
f called with arguments: x = c(1, 2, 1, 2) y = c(3, 3, 4, 4)
[,1] [,2]
[1,] 3 4
[2,] 6 8
注意生成的组合。
如果我们不能保证函数可以处理向量参数,那么有一个简单的技巧可以确保函数只为组合中的每一对调用一次:Vectorize
。这创建了另一个函数,它为参数中的每个元素调用一次原始函数:
> Vectorize(f)(c(1,2),c(3,4))
f called with arguments: x = 1 y = 3
f called with arguments: x = 2 y = 4
[1] 3 8
所以我们可以用它来制作一个“安全”outer
:
> outer(c(1,2), c(3,4), Vectorize(f))
f called with arguments: x = 1 y = 3
f called with arguments: x = 2 y = 3
f called with arguments: x = 1 y = 4
f called with arguments: x = 2 y = 4
[,1] [,2]
[1,] 3 4
[2,] 6 8
在这种情况下,结果是相同的,因为f
是以矢量化方式编写的,即因为"*"
是矢量化的。但是如果你的功能没有考虑到这一点,直接在outer
中使用它可能会失败,或者(更糟)可能会给出错误的结果。