Reputation: 149
I am trying to store multiple plots produced by ggplot2
into a list.
I am attempting to use the list function suggested in a previous thread, however I am having difficulty creating my own function to meet my needs.
First, I split a dataframe based on a factor into a list with the following code:
heatlist.germ <- split(heatlist.germ, f=as.factor(heatlist.germ$plot))
Afterwhich, I attempt to create a list function that I can later use lapply
with.
plot_data_fcn <- function (heatlist.germ) {
ggplot(heatlist.germ[[i]], aes(x=posX, y=posY, fill=germ_bin)) +
geom_tile(aes(fill=germ_bin)) +
geom_text(aes(label=germ_bin)) +
scale_fill_gradient(low = "gray90", high="darkolivegreen4") +
ggtitle(plot) +
scale_x_continuous("Position X", breaks=seq(1,30)) +
scale_y_continuous("Position Y (REVERSED)", breaks=seq(1,20))
}
heatlist.test <- lapply(heatlist.germ[[i]], plot_data_fcn)
Two main things I am trying to accomplish:
plot
) in a list.Any help would be appreciated.
Upvotes: 2
Views: 1113
Reputation: 161155
I don't have your data, so I'll simplify the plotting mechanism.
The first problem is that you should not use your [[i]]
referencing in your function. Just have your function deal with data as-is, it really doesn't know that its argument is (in another environment) an element with a list. It knows just the object itself.
# a simple plot function
myfunc <- function(x) ggplot(x, aes_string(names(x)[1], names(x)[2])) + geom_point()
# a list of frames, nothing fancy here
datalist <- replicate(3, mtcars, simplify = FALSE)
# just call it ...
myplots <- lapply(datalist, myfunc)
class(myplots[[1]])
# [1] "gg" "ggplot"
When myfunc
is called, its argument x
is just a data.frame
, the function has no idea that x
is the first (or second or third) frame in a list of frames.
If you want to include the nth frame with an index indicating which element it is, this is in my view "zipping" data together, so I suggest Map
. (You can also use purrr::imap
or related tidyverse functions.)
myfunc2 <- function(x, title = "") ggplot(x, aes_string(names(x)[1], names(x)[2])) + geom_point() + labs(title = title)
myplots <- Map(myfunc2, datalist, sprintf("Plot number %s", seq_along(datalist)))
class(myplots[[1]])
# [1] "gg" "ggplot"
To understand how Map
relates to lapply
, then understand that lapply(datalist, myfunc)
is "unrolled" to something like:
myfunc(datalist[[1]])
myfunc(datalist[[2]])
myfunc(datalist[[3]])
With Map
, however, it takes one function that must accept one or more arguments in each call. With that, Map
accepts as many lists (or vectors) as the function accepts arguments. The two functions are synonomously
lapply(datalist, myfunc) # data first, function second
Map(myfunc, datalist) # function first, data second
and a more complicated call unrolls like thus:
titles <- sprintf("Plot number %d", seq_along(datalist)) # "Plot number 1", ...
Map(myfunc2, datalist, titles)
# equivalent to
myfunc2(datalist[[1]], titles[[1]])
myfunc2(datalist[[2]], titles[[2]])
myfunc2(datalist[[3]], titles[[3]])
It doesn't really matter if each of the arguments is a true list
(as in datalist
) or a vector (as in titles
), as long as they are the same length (or length 1).
Upvotes: 5