我正在尝试编写一个函数,该函数使用不同的步长值绘制与ODE解相关的相同图形近似值。我得到了ODE近似值,我无法弄清楚如何添加识别每个函数的颜色和图例。
我试图关注this answer,但我无法将其很好地转换为函数数量不恒定的上下文。
这是我的代码及其生成的输出。
library(purrr)
library(ggplot2)
library(glue)
eulerMethod = function(f, t0, y0, h, memo = 1000) {
vec = double(memo + 1)
vec[1] = y0
for (i in 1:memo) {
vec[i+1] = vec[i] + h*f(t0 + i*h, vec[i])
}
solution = function(t) {
if (t < t0) return(NaN)
n = (t-t0)/h
intN = floor(n)
if (n == intN)
return(vec[n+1])
else # linear interpolation
return(vec[intN + 1] + (n - intN) * (vec[intN + 2] - vec[intN + 1]))
}
}
compare = function(f, t0, y0, interval, hs = c(1, 0.5, 0.2, 0.1, 0.05)) {
fs = map(hs, ~ eulerMethod(f, t0, y0, .)) %>%
map(Vectorize)
# generates "h = 1" "h = 0.5" ... strings
legends = map_chr(hs, ~ glue("h = {hs[[.]]}"))
map(1:length(hs), ~ stat_function(fun = fs[[.]],
geom = "line",
aes_(colour = legends[.]))) %>%
reduce(`+`, .init = ggplot(data.frame(x = interval), aes(x)))
}
# y' = y => solution = exp(x)
compare(function(t, y) y, 0, 1, c(0, 5))
答案 0 :(得分:1)
我之前没有使用过glue
,但它并没有像我想象的那样工作。它只返回了h = 1
的五份副本。我修改了您的代码,只使用paste0
来创建图例值:
compare = function(f, t0, y0, interval, hs = c(1, 0.5, 0.2, 0.1, 0.05)) {
fs = map(hs, ~ eulerMethod(f, t0, y0, .)) %>%
map(Vectorize)
# generates "h = 1" "h = 0.5" ... strings
legends = paste0("h = ", hs)
map(1:length(hs), ~ stat_function(fun = fs[[.]],
geom = "line",
aes_(colour = legends[.]))) %>%
reduce(`+`, .init = ggplot(data.frame(x = interval), aes(x, colour=.)))
}
compare(function(t, y) y, 0, 1, c(0, 5))
此外,在我看来,代码可以更简单一些。例如:
compare = function(f, t0, y0, interval, hs = c(1, 0.5, 0.2, 0.1, 0.05)) {
fs = map(hs, ~ eulerMethod(f, t0, y0, .)) %>%
map(Vectorize)
ggplot(data.frame(x = interval), aes(x)) +
map(1:length(fs), function(nn) {
stat_function(fun = fs[[nn]], geom = "line", aes_(colour = factor(hs[nn])))
}) +
labs(colour="h")
}
compare(function(t, y) y, 0, 1, c(0, 5))