I'm trying to add multiple lines to a saved ggplot object. The coordinates for the lines are stored on a list of dataframes, one data frame for each individual plot. I successfully have created multiple plots using lapply, however, the code fails when calling the geom_segment. Below example data and code.
library(ggplot2)
library(tidyverse)
data(iris)
#Dataframes
m.slen <- iris[,c(1,5)]
m.swid <- iris[,c(2,5)]
m.plen <- iris[,c(3,5)]
m.pwid <- iris[,c(4,5)]
#List of dataframes
m.list = list(m.slen = m.slen,
m.swid = m.swid,
m.plen = m.plen,
m.pwid = m.pwid)
#Setting col names
m.list <- lapply(m.list, setNames, nm = c("data", "species"))
#Creating list of data frames with coordinates for geom_segment
meanV = lapply(m.list, function(x) mean(x$data, na.rm = TRUE))
coordy1 = lapply(m.list, function(x) x %>%
group_by(species) %>%
summarise(max = max(data, na.rm=TRUE)) %>%
pull(max) 2)
#Table with dynamic values
line.plot <- list()
for(i in 1:4) {
line.plot[[i]] <-
tibble(x1 = meanV[[i]],
x2 = meanV[[i]] 1,
y1 = coordy1[[i]][1],
y2 = coordy1[[i]][1])
}
#Creating first set of plots, using first list of DFs
plots <- lapply(m.list,function(x)
p <- ggplot(x, aes( x= data, fill = species))
geom_histogram(stat = "count")
ggtitle(names(m.list)))
print(plots)
#Adding segments using second list of DFs
final_plots <- lapply(plots,function(x)
plots geom_segment(data = line.plot,
aes(x = x1, y = y1, xend = x2, yend = y2)))
Everything works until the last step, I get the following error
Error in
fortify()
: !data
must be a data frame, or other object coercible byfortify()
, not a list
Any input or advice is welcome. Thanks
CodePudding user response:
The issue is that line.plot
is a list. To achieve your desired result you could use purrr::map2
to loop over both your list of plots and the list of dataframes for the segments:
Note: I also added inherit.aes = FALSE
to geom_segment
because otherwise you will get an error, too.
final_plots <- purrr::map2(plots, line.plot, function(x, y) {
x geom_segment(
data = y,
aes(x = x1, y = y1, xend = x2, yend = y2), inherit.aes = FALSE
)
})
final_plots[[1]]
EDIT Using base R you could achieve the same result with mapply
:
final_plots <- mapply(function(x, y) {
x geom_segment(
data = y,
aes(x = x1, y = y1, xend = x2, yend = y2), inherit.aes = FALSE
)
}, x = plots, y = line.plot, SIMPLIFY = FALSE)
or thanks to the comment by @Parfait using Map
:
final_plots <- Map(function(x, y) {
x geom_segment(
data = y,
aes(x = x1, y = y1, xend = x2, yend = y2), inherit.aes = FALSE
)
}, x = plots, y = line.plot)