rggplot2lapplygeom-textggtitle

How to assign unique title and text labels to ggplots created in lapply loop?


I've tried about every iteration I can find on Stack Exchange of for loops and lapply loops to create ggplots and this code has worked well for me. My only problem is that I can't assign unique titles and labels. From what I can tell in the function i takes the values of my response variable so I can't index the title I want as the ith entry in a character string of titles.

The example I've supplied creates plots with the correct values but the 2nd and 3rd plots in the plot lists don't have the correct titles or labels.

Mock dataset:

library(ggplot2)

nms=c("SampleA","SampleB","SampleC")
measr1=c(0.6,0.6,10)
measr2=c(0.6,10,0.8)
measr3=c(0.7,10,10)
qual1=c("U","U","")
qual2=c("U","","J")
qual3=c("J","","")
df=data.frame(nms,measr1,qual1,measr2,qual2,measr3,qual3,stringsAsFactors = FALSE)

identify columns in dataset that contain response variable

measrsindex=c(2,4,6)

Create list of plots that show all samples for each measurement

plotlist=list()
plotlist=lapply(df[,measrsindex], function(i) ggplot(df,aes_string(x="nms",y=i))+
             geom_col()+
             ggtitle("measr1")+
             geom_text(aes(label=df$qual1)))

Create list of plots that show all measurements for each sample

plotlist2=list()
plotlist2=lapply(df[,measrsindex],function(i)ggplot(df,aes_string(x=measrsindex, y=i))+
              geom_col()+
              ggtitle("SampleA")+
              geom_text(aes(label=df$qual1)))

The problem is that I cant create unique title for each plot. (All plots in the example have the title "measr1" or "SampleA)

Additionally I cant apply unique labels (from qual columns) for each bar. (ex. the letter for qual 2 should appear on top of the column for measr2 for each sample)

Additionally in the second plot list the x-values aren't "measr1","measr2","measr3" they're the index values for those columns which isn't ideal.

I'm relatively new to R and have never posted on Stack Overflow before so any feedback about my problem or posting questions is welcomed.

I've found lots of questions and answers about this sort of topic but none that have a data structure or desired plot quite like mine. I apologize if this is a redundant question but I have tried to find the solution in previous answers and have been unable.

This is where I got the original code to make my loops, however this example doesn't include titles or labels: Looping over ggplot2 with columns


Solution

  • I would recommend putting your data in long format prior to using ggplot2, it makes plotting a much simpler task. I also recoded some variables to facilitate constructing the plot. Here is the code to construct the plots with lapply.

    library(tidyverse)
    
    #Change from wide to long format
    df1<-df %>% 
      pivot_longer(cols = -nms,
                   names_to = c(".value", "obs"),
                   names_sep = c("r","l")) %>%
      #Separate Sample column into letters
      separate(col = nms,
               sep = "Sample",
               into = c("fill","Sample"))
    
    #Change measures index to 1-3
    measrsindex=c(1,2,3)
    
    plotlist=list()
    plotlist=lapply(measrsindex, function(i){
      #Subset by measrsindex (numbers) and plot
      df1 %>%
        filter(obs == i) %>%
        ggplot(aes_string(x="Sample", y="meas", label="qua"))+
        geom_col()+
        labs(x = "Sample") +
        ggtitle(paste("Measure",i, collapse = " "))+
        geom_text()})
    
    #Get the letters A : C
    samplesvec<-unique(df1$Sample)
    
    plotlist2=list()
    plotlist2=lapply(samplesvec, function(i){
      #Subset by samplesvec (letters) and plot
      df1 %>%
        filter(Sample == i) %>%
        ggplot(aes_string(x="obs", y = "meas",label="qua"))+ 
        geom_col()+
        labs(x = "Measure") +
        ggtitle(paste("Sample",i,collapse = ", "))+
        geom_text()})
    

    Watching the final plots, I think it might be useful to use facet_wrap to make these plots. I added the code to use it with your plots.

    #Plot for Measures
    ggplot(df1, aes(x = Sample, 
                    y = meas, 
                    label = qua)) +
      geom_col()+
      facet_wrap(~ obs) +
      ggtitle("Measures")+
      labs(x="Samples")+
      geom_text()
    
    #Plot for Samples
    ggplot(df1, aes(x = obs, 
                    y = meas, 
                    label = qua)) +
      geom_col()+
      facet_wrap(~ Sample) +
      ggtitle("Samples")+
      labs(x="Measures")+
      geom_text()
    

    Here is a sample of the plots using facet_wrap.

    Measures