I am writing a plotting method for class "foo"
. I would like this plot function to take multiple foo
objects and plot them on the same graph.
#parabola function
parabolas <- function(x, parm) {
y <- parm[1]*(x^2)+parm[2]*x+parm[3]
return(y)
}
#make foo object
make_foo <- function(a, b, c) {
x <- runif(100, 0 , 20)
y <- parabolas(x = x, parm = c(a,b,c)) + rnorm(100, mean = 100 ,sd = 100)
foo <- list(data = data.frame(x = x, y = y), parameters = c(a,b,c))
class(foo) <- "foo"
return(foo)
}
#plot function
plot.foo <- function(x,
...,
labels) {
a <- ggplot(NULL, aes(x = x, y = y))
foo.list <- list(x, ...)
#browser()
#build plot
for(i in 1:length(foo.list)){
foo.obj <- foo.list[[i]]
foo.obj$data$lab <- factor(rep(labels[i], nrow(foo.obj$data)), levels = labels)
a <- a + geom_point(data = foo.obj$data, size = 5, alpha = .7, aes(color = lab))
a <- a + stat_function(data = foo.obj$data,
fun = parabolas,
args = list(parm = foo.obj$parameters), size = 1.2)
}
return(a)
}
ggplot will relevel the factor levels of lab
according to the alphabetical order of the factor labels. I do not know how to choose the factor level order for lab
when adding these layers sequentially. I would like for the first element of labels
to correspond to the first foo object plotted, and the second element to correspond to the second foo object, and so forth and so forth.
foo1 <- make_foo(2, 10, 3)
foo2 <- make_foo(-6, -3, 2000)
plot(foo1, foo2, labels = c("obj1","obj2"))
#label for foo1 is "obj1" and label for foo2 is "obj2"
plot(foo1, foo2, labels = c("obj3","obj2"))
#label for foo1 should be "obj3" and label for foo2 should be "obj2"
The reason I structure the plot function like this as opposed to binding the data frames together and assigning the correct factor levels to lab
is because in that particular case, facet_wrap
and stat_function
do not work well together. After applying multiple stat_function
and using facet_wrap
together, all curves will appear in each panel. This thread illustrates a similar problem.
Because I have these different layers limited to different data sets, facet_wrap
will correctly facet each stat_function
plot according to the data/parameters used to draw it.
plot(foo1, foo2, labels = c("z","a")) + facet_wrap(~lab, scales = "free")
#Shows facet_wrap works as intended but the labels for foo1 and foo2 are
#still not in the intended order
You can manually override the order of the color scale by setting the limits
. Here is how:
plot.foo <- function(x,
...,
labels) {
a <- ggplot(NULL, aes(x = x, y = y))
foo.list <- list(x, ...)
#browser()
#build plot
for(i in 1:length(foo.list)){
foo.obj <- foo.list[[i]]
foo.obj$data$lab <- factor(rep(labels[i], nrow(foo.obj$data)), levels = labels)
a <- a + geom_point(data = foo.obj$data, size = 5, alpha = .7, aes(color = lab))
a <- a + stat_function(data = foo.obj$data,
fun = parabolas,
args = list(parm = foo.obj$parameters), size = 1.2)
}
### added line:
a <- a + scale_color_discrete(limits = labels)
###
return(a)
}