我有一个名为{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc",
"balance": 30,
"accounts": ["/account/12345", "/account/67890"]
}
的小R
函数。我正在尝试允许该函数的用户为参数ab
或vector
(不是两者)提供m
。
问题:
我想知道如何设置s
循环,以便根据用户的选择选择性地循环for
或m
? [在这里使用s
会更好吗?]
这是我的R代码没有成功:
Vectorize
答案 0 :(得分:2)
一想法:
ab <- function(m, s, lo = -Inf, hi = Inf) {
if (length(m) > 1) {
if (length(s) > 1) {
warning("'m' and 's' are both long, truncating 's'")
}
s <- rep(s[1], length(m))
} else {
m <- rep(m, length(s))
}
# something else here ...
}
所有这一切都是确保两个变量的长度相同,从而迫使一个变量成为不变的变量。 (我认为这就是你要做的......)
我认为你不能有效地对基本计算进行矢量化,因为(除其他事项外)integrate
确实需要一次处理一个问题。为了改进任何事情,我可能会建议进行所有计算并将所有值都返回到单个列表中。从那里开始,单独绘制线条非常简单:
ab <- function(m, s, lo = -Inf, hi = Inf,
xrange = c(-3, 3), n = 50) {
if (length(m) > 1) {
if (length(s) > 1) {
warning("'m' and 's' are both long, truncating 's'")
}
s <- rep(s[1], length(m))
} else {
m <- rep(m, length(s))
}
xs <- seq(xrange[1], xrange[2], length = n)
out <- mapply(function(a,b) {
p = function(x) dnorm(x, a, b)
f = function(x) p(x) / integrate(p, lo, hi)[[1]]
list(x = xs, y = sapply(xs, f))
}, m, s, SIMPLIFY = FALSE)
out
}
ret <- ab(m = c(0, .5), s = 1)
str(ret)
# List of 2
# $ :List of 2
# ..$ x: num [1:50] -3 -2.88 -2.76 -2.63 -2.51 ...
# ..$ y: num [1:50] 0.00443 0.00635 0.00897 0.01247 0.01709 ...
# $ :List of 2
# ..$ x: num [1:50] -3 -2.88 -2.76 -2.63 -2.51 ...
# ..$ y: num [1:50] 0.000873 0.00133 0.001996 0.002951 0.004298 ...
从这里开始,你应该能够一次性地绘制所有内容:
yrange <- c(0, max(sapply(ret, `[[`, "y")))
plot(0, type = 'n', xlim = c(-3,3), ylim = yrange,
ylab = "Density", xlab = "Z")
ign <- mapply(function(d,i) lines(y~x, data=d, col=i),
ret, seq_along(ret))
将计算部分与绘图部分分开,通常有利于(恕我直言)计算速度,无需重新计算的情节再现以及代码组织。
答案 1 :(得分:0)
我非常感谢我们的同事@r2evans
给出了答案,但我认为这个问题可能有一个更简单的解决方案(即一行if
语法):
ab = function(m, s, lo = -Inf, hi = Inf){
loop = if(length(m) > 1) length(m) else length(s)
p = if(length(m) > 1) function(x) dnorm(x, m[i], s) else function(x) dnorm(x, m, s[i])
for(i in 1:loop){
f = function(x) p(x)/integrate(p, lo, hi)[[1]]
curve(f, -3, 3, add = i!= 1, col = i)
}
}
# Example of use:
ab(m = c(0, 1), 1)
#Example of use:
ab(m = 0, c(1, 2))