How can you use ggplot to automatically overlay many plots of related functions?
I have a family of functions that are all the same except for one configurable parameter, and I want to plot all of these functions on one set of axes superimposed on each other. For example, it could be sin (n * x), with different values ββfor n, like 1:30, and I don't want to have to type every command every time - I suppose there must be some way to do it programmatically.
library(ggplot2)
define trigger functions as a function of frequency: sin (x), sin (2x), sin (3x), etc.
trigf <- function(i)(function(x)(sin(i*x)))
Overlay of two functional graphs - this works by hand, of course
ggplot(data.frame(x=c(0,pi)), aes(x)) + stat_function(fun=trigf(1)) + stat_function(fun=trigf(2))
now try to generalize - my idea was to make a list of stat_functions using lapply
plotTrigf <- lapply(1:5, function(i)(stat_function(fun=function(x)(sin(i*x))) ))
try using the list items manually but it doesn't actually work - only the graph is displayed i=5
and I'm not sure why when this is not what I was referencing
ggplot(data.frame(x=c(0,pi)), aes(x)) +plotTrigf[[1]] + plotTrigf[[2]]
I thought this one Reduce
might handle a "sum total" to add to ggplot()
, but it doesn't work - it complains about a non-numeric argument to a binary operator
Reduce("+", plotTrigf)
So, I kind of got stuck doing this strategy or maybe there was another way to do it.
source to share
Are you using version R <3.2? The problem is that you really need to evaluate your parameter i
in your call lapply
. Right now, this is left as a promise and not questioned until you try to plot a plot, at which point it i
has the last meaning it had in a loop lapply
which is 5. Use:
plotTrigf <- lapply(1:5, function(i) {force(i);stat_function(fun=function(x)(sin(i*x))) })
You cannot just add stat_function
calls together, even without Reduce()
you get an error
stat_function(fun=sin) + stat_function(fun=cos)
# Error in stat_function(fun = sin) + stat_function(fun = cos) :
# non-numeric argument to binary operator
You need to add them to the ggplot object. You can do it with Reduce()
if you just give the parameterinit=
Reduce("+", plotTrigf, ggplot(data.frame(x=c(0,pi)), aes(x)))
And in fact the special +
operator for ggplot objects allows you to add a list of objects so you don't need to at all Reduce
(see code for ggplot2:::add_ggplot
)
ggplot(data.frame(x=c(0,pi)), aes(x)) + plotTrigf
Final result
source to share
You need to use force
to make sure the parameter is being evaluated at the right time. This is a very useful technique and a common source of confusion about loops, you should read about it in Hadley's book http://adv-r.had.co.nz/Functions.html
To solve your question: you just need to add force(i)
when defining all graphs inside the function lapply
before making the call stat_function
. Then you can use the Shrink method or any other method to combine them. Here it is possible to combine the plots with lapply
(note that I am using the operator <<-
which is discouraged)
p <- ggplot(data.frame(x=c(0,pi)), aes(x))
lapply(plotTrigf, function(x) {
p <<- p + x
return()
})
source to share