looping figure creation, but needing to input different species name each iteration

58 views
Skip to first unread message

henn...@d.umn.edu

unread,
Dec 17, 2015, 5:30:09 PM12/17/15
to ggplot2
I posted yesterday and received a couple of responses (Thanks to those who did), but my needs have evolved slightly.  
I am creating figures for 75 species at nine different park units and may have need to do this several times, so I'm really in need of a method to loop this process to create consistent figures quickly.

The looping itself was quite easy to figure out, however I'm having difficulties creating a title that satisfies three criteria:

a. I need to italicize the species name which is contained within the figure title (i.e.Mean Suitability in Anonymous National Park for Canus lupus by Year)
b. It should be able to wrap to at least two rows so the title is not wider than the figure itself.
c. Since I am looping this, I need to draw the species name to be italicized from the dataset that I am creating the figure from.  

the below code is what I've figured out so far.  The part that I cannot for the life of me figure out is how to reference the variable i (which represents the genus species name) to be italicized.  Any help anyone could provide would be greatly, greatly appreciated.  Thanks.

for( i in unique(park$species)) {
  
  myplot<- subset(park, species==i)
  my_title <- paste("Mean Suitability in Anonymous National\nPark for", i, "by Year")
  plotprint=ggplot(myplot, aes(x=year, y=MEAN, group=rcp))+geom_line(size=1,aes(colour= factor(rcp)))+geom_point(aes(colour=factor(rcp)))+labs(title = my_title, x="Projection Year", y="Mean Suitability\nValue")+scale_x_continuous(breaks=c(2015,2025,2050,2075,2095))+scale_y_continuous(limits = c(0,1),breaks=c(0.2,0.4,0.6,0.8,1.0))+theme(panel.grid.major = element_blank(),panel.grid.minor=element_blank(),panel.background = element_rect(fill = "white"), plot.title = element_text(vjust=1.5, size=14),axis.title.y=element_text(vjust=1),panel.border = element_rect(colour = "black", fill=NA, size=1),axis.title.x=element_text(vjust=-0.1),axis.text.x=element_text(vjust=0.2, colour="black"), axis.text.y=element_text(colour="black"))+scale_colour_manual(name="factor", breaks=c("group1","group2"), labels=c("Group 1","Group 2"),values=c("group1"="blue","group2"="red"))
  ggsave(paste0(i,".png"), width=6, height=2.5,plotprint)
}

species          rcp    year    park    MEAN
species_genus   group1  2010    ANON    0.544363995
species_genus   group2  2010    ANON    0.474398504
species_genus   group1  2015    ANON    0.497079159
species_genus   group2  2015    ANON    0.571342493
species_genus   group1  2020    ANON    0.539996331
species_genus   group2  2020    ANON    0.522597844
species_genus   group1  2025    ANON    0.464497998
species_genus   group2  2025    ANON    0.479889333
species_genus   group1  2030    ANON    0.539434493
species_genus   group2  2030    ANON    0.516314661
species_genus   group1  2035    ANON    0.445646996
species_genus   group2  2035    ANON    0.466872344
species_genus   group1  2040    ANON    0.461644833
species_genus   group2  2040    ANON    0.382267167
species_genus   group1  2045    ANON    0.371176163
species_genus   group2  2045    ANON    0.299473159
species_genus   group1  2050    ANON    0.316472329
species_genus   group2  2050    ANON    0.143133335
species_genus   group1  2055    ANON    0.354656503
species_genus   group2  2055    ANON    0.161598501
species_genus   group1  2060    ANON    0.167542666
species_genus   group2  2060    ANON    0.143555
species_genus   group1  2065    ANON    0.138111168
species_genus   group2  2065    ANON    0.127673333
species_genus   group1  2070    ANON    0.121445348
species_genus   group2  2070    ANON    0.126145499
species_genus   group1  2075    ANON    0.342944995
species_genus   group2  2075    ANON    0.127160334
species_genus   group1  2080    ANON    0.163886666
species_genus   group2  2080    ANON    0.136789334
species_genus   group1  2085    ANON    0.157619332
species_genus   group2  2085    ANON    0.116568
species_genus   group1  2090    ANON    0.157446332
species_genus   group2  2090    ANON    0.131710666
species_genus   group1  2095    ANON    0.155704334
species_genus   group2  2095    ANON    0.106103182

Tom Philippi

unread,
Dec 17, 2015, 6:26:07 PM12/17/15
to henn...@d.umn.edu, ggplot2
One approach would be to use plotmath, something like:
     my_title <- expression(paste("Mean Suitability in Anonymous National\nPark for",italics(species)i, "by Year"))
Plotmath lets you include many mathematical symbols as well as italicize, underline, superscript & subscript in title & label strings.

?expression and ?plotmath and perhaps googling "plotmath ggplot2" should get you what you need.

Tom Philippi
Quantitative Ecologist & Data Therapist
Inventory and Monitoring Program
National Park Service



--
--
You received this message because you are subscribed to the ggplot2 mailing list.
Please provide a reproducible example: https://github.com/hadley/devtools/wiki/Reproducibility
 
To post: email ggp...@googlegroups.com
To unsubscribe: email ggplot2+u...@googlegroups.com
More options: http://groups.google.com/group/ggplot2

---
You received this message because you are subscribed to the Google Groups "ggplot2" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ggplot2+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dennis Murphy

unread,
Dec 17, 2015, 10:20:42 PM12/17/15
to henn...@d.umn.edu, ggplot2
Hi:

1. You need to simplify your plot call - the calls to theme() are
unnecessary for the purposes of your question.
2. Your code got mashed together likely because you sent your mail in
HTML; therefore, it wasn't easy to read.

Complaints aside, the biggest programming problem was to combine
normal and italic fonts in the title across two lines and avoid
getting a large space between the end of the first text chunk and the
italicized text. From your end, you have to distinguish the contents
of an atomic vector from their respective indices/locations. Below is
one way to do what I think you requested. I made up a fake data set to
generate multiple species; you could extend the idea to species-park
combinations if that is of interest.


# Fake data set - year is numeric rather than factor, so a group
# aesthetic for it is unnecessary.
DF <- data.frame(
species = factor(rep(paste0("species_", LETTERS[1:3]), each = 10)),
rcp = c("group1", "group2"),
year = rep(2011:2015, each = 2),
MEAN = runif(30, 0.3, 0.6))

library(ggplot2)

# define an atomic vector of species names
species_names <- as.character(unique(DF$species))

# A function to create a plot for an individual species. It takes a
# data frame DF and a character object species_name as formal arguments

plotfun <- function(DF, species_name)
{
d <- DF[DF$species == species_name, ] # get the data subset

# Manufacture an expression that creates a two-line title
my_title <- bquote(atop(paste("Mean Suitability for ",
italic(.(species_name)), " by Year"),
"Anonymous National Park"))

# create and return the ggplot
ggplot(d, aes(x = year, y = MEAN, colour = rcp)) +
geom_point() +
geom_line() +
labs(title = my_title, x = "Projection Year",
y="Mean Suitability\nValue", colour = "factor")
}

# Apply the above function to each species, return a list of ggplot objects
L <- lapply(species_names,
function(x) plotfun(DF, x))

# Cycle through the list of plots and save them to individual files
for(i in seq_along(species_names))
{
filename <- paste(species_names[i], "png", sep = ".")
ggsave(filename, L[[i]], width = 6, height = 2.5)
}

Creating axis titles and main titles in a plot can sometimes be a
challenge, particularly when one needs to insert non-standard text
such as mathematics or text in a modified font. The challenge here was
to create a main title with two lines that mixes normal and italic
text. \n works when given a text string without 'embellishments', but
unexpected things can happen if your input is an expression rather
than a string. I made two adjustments: (i) I used atop() because it
can take an expression or a string as an argument; (ii) I modified the
title so that the italicized text was on the first line inside an
expression().

The code above cycles through each species name, first taking the
appropriate data subset and then producing and returning a plot with a
two-line main title. The lapply() call produces a list of plots, one
per species. The loop at the end cycles through the list, saving each
plot to a file in png format. I find it useful to save the plots in a
list in case you need to reference them later. If you don't want the
list of plots, assign the ggplot() output to an object, say p, inside
plotfun() and make its last line

ggsave(p, file = paste(species_name, "png", sep = ".", width = 6, height = 2.5))


HTH,
Dennis

On Thu, Dec 17, 2015 at 2:30 PM, <henn...@d.umn.edu> wrote:

Roman Luštrik

unread,
Dec 18, 2015, 3:25:46 AM12/18/15
to Dennis Murphy, henn...@d.umn.edu, ggplot2
Another good option for concatenating text is `sprintf` function. Wrap that into `expression` and you're all set.

Cheers,
Roman
--
In God we trust, all others bring data.

henn...@d.umn.edu

unread,
Dec 21, 2015, 12:27:24 PM12/21/15
to ggplot2, henn...@d.umn.edu
Hi Dennis,

I'll be aware of your suggestions next time.  Thanks.  

Your suggestions worked quite well.  The key to modifying what I had done to get it all to work was the addition of nesting atop inside of bquote.  

  myplot<- subset(anon, species==i)
  my_title<-bquote(atop(paste("Mean Suitability for ", italic(.(i)), " by Year"), "Anonymous National Park"))

thanks so much for you help.  This will be a huge time saver.

Kris
Reply all
Reply to author
Forward
0 new messages