Search code examples
rloopsplottitle

Change titles for each subplot using loop in R


I am trying to change title of each subplot using loop in R. I know there is a similar question here but I was not able to apply this in my case. Here are my data and codes:

# Pet size data and their names
color <- c('W', 'B', 'G', 'W', 'B', 'G', 'W', 'B', 'G', 'W', 'B', 'G', 'W', 'B', 'G', 'W', 'B', 'G')
mass <- c(10, 14, 20, 11, 16, 13, 11, 15, 10, 14, 23, 18, 12, 22, 20, 13, 14, 17)
name <- c('B', 'B', 'B', 'F', 'F', 'F', 'D', 'D', 'D', 'A', 'A', 'A', 'C', 'C', 'C', 'E', 'E', 'E')

# Make it into data frame
pet.stats <- data.frame(color, mass, name)

# Name of pets (I want to plot them by type of pets)
kitty <- c('A', 'B', 'C')
bunny <- c('D', 'E', 'F')

all.pets <- append(kitty, bunny)
all.pets <- as.factor(all.pets)

par(mfrow = c(2, 3), mar = c(4, 4, 2, 1), oma = c(0.5, 0.5, 0.5, 0.5), mgp = c(2.2, 0.7, 0))

# Loop through pet names and give title with pet type and pet name for each subplot
for (i in 1: nlevels(pet.stats$name)) {
barplot(pet.stats$mass[pet.stats$name == levels(pet.stats$name)[i]],
main = substitute(paste('Size of ', bold('lovely'),
ifelse(pet.stats$name[i] %in% kitty, 'kitty', 'bunny'),
' (', levels(pet.stats$name[i]), ')')),
xlab = 'Color', ylab = 'Mass', names = c('White', 'Black', 'Gray'))
abline(h = 0)
}

and this is what I get:

enter image description here

I want each subplot to have a title "Size of lovely (pet type) (pet name)" such as "Size of lovely bunny 'D'"

Could somebody please help fix what I am doing wrong? Thank you.


Solution

  • Ok, so here is you solution. The problem was with R and non-standard evaluation. The substitute function was freezing the evaluation of functions. The way to get the desired behaviour, is to specify in the env variable what you need to have evaluated.

    Note, I broke out each of the variables and then constructed them in the main. This makes it a little easier to see what is happening.

    # Pet size data and their names
    color <- c('W', 'B', 'G', 'W', 'B', 'G', 
               'W', 'B', 'G', 'W', 'B', 'G', 
               'W', 'B', 'G', 'W', 'B', 'G')
    mass <- c(10, 14, 20, 11, 16, 13, 11, 15, 
              10, 14, 23, 18, 12, 22, 20, 13, 14, 17)
    name <- c('B', 'B', 'B', 'F', 'F', 'F', 'D', 
              'D', 'D', 'A', 'A', 'A', 'C', 'C', 
              'C', 'E', 'E', 'E')
    
    # Make it into data frame
    pet.stats <- data.frame(color, mass, name)
    
    # Name of pets (I want to plot them by type of pets)
    kitty <- c('A', 'B', 'C')
    bunny <- c('D', 'E', 'F')
    
    all.pets <- append(kitty, bunny)
    all.pets <- as.factor(all.pets)
    

    Now note the list of variables passed to substitute

    
    par(mfrow = c(2, 3), mar = c(4, 4, 2, 1), oma = c(0.5, 0.5, 0.5, 0.5), mgp = c(2.2, 0.7, 0))
    
    # Loop through pet names and give title with pet type and pet name for each subplot
    for (i in 1: nlevels(pet.stats$name)) {
    
    # Break out the names
      animal_type <- ifelse(pet.stats$name[i] %in% kitty, 'kitty', 'bunny')
      animal_names <- levels(pet.stats$name)[i]
    
      barplot(pet.stats$mass[pet.stats$name == levels(pet.stats$name)[i]],
              main = substitute(paste('Size of ', bold('lovely'),
                                      animal_type,
                                      ' (', animal_names, ')'),
                                env = list(animal_type = animal_type,
                                           animal_names = animal_names)),
              xlab = 'Color', ylab = 'Mass', names = c('White', 'Black', 'Gray'))
      abline(h = 0)
    }