Add labels to all factors in interaction plot with ggplot2

344 views
Skip to first unread message

kw...@harveyecology.com

unread,
Sep 21, 2018, 12:04:19 AM9/21/18
to Davis R Users' Group
Hi all! 

I am trying to add the labels for significant differences between combinations of two factors, and am having some difficulties. 

I have a negative binomial mixed model with multiple nesting levels and random factors, with a count response. All of my predictors are categorical. I chose my final model and ran this through lsmeans() and cld() to do pairwise comparisons for significant factors and interactions. 

When I have one factor with any number of levels, my code works fine. 
For example (where test5 is my glmm, and SamplePer is the factor of interest): 

SamplePer = lsmeans(test5, ~ SamplePer) 
SamplePer = cld(SamplePer, alpha=0.10, Letters=letters, adjust="tukey")

Which gives an object of type 'summary_emm' and 'data.frame' looking like this: 
 SamplePer     lsmean        SE df  asymp.LCL asymp.UCL .group
 Apr1       -0.4863283 0.2632676 NA -1.1789954 0.2063388 a     
 Mar2       0.1105724 0.2221710 NA -0.4739680 0.6951129 ab    
 Mar1       0.4999976 0.2771670 NA -0.2292395 1.2292346 b     
 Feb2       0.8025046 0.2814722 NA  0.0619406 1.5430687 bc    
 Feb1       1.5699948 0.2515543 NA  0.9081458 2.2318437 cd    
 Jan         1.8281466 0.2520075 NA  1.1651054 2.4911879 d     
Results are averaged over the levels of: PlotType, WaterDepth, TideStage, Subarea 
Confidence level used: 0.95 
Conf-level adjustment: sidak method for 6 estimates 
P value adjustment: tukey method for comparing a family of 6 estimates 
significance level used: alpha = 0.1 

Let's not even get into the topic of p-values please, I know. LOL. Anyway.

### Order the levels for printing
SamplePer$SamplePer = factor(SamplePer$SamplePer,
                      levels=c("Jan","Feb1","Feb2","Mar1","Mar2","Apr1"))
###  Remove spaces in .group  
SamplePer$.group=gsub(" ", "", SamplePer$.group)
pd = position_dodge(0.4)
###  Plot 
ggplot(SamplePer,
       aes(x     = SamplePer,
           y     = lsmean,
           label = .group)) +
  geom_point(shape  = 15,
             size   = 4,
             position = pd) +
  geom_errorbar(aes(ymin  =  asymp.LCL,
                    ymax  =  asymp.UCL),
                width =  0.2,
                size  =  0.7,
                position = pd) +
  theme_bw() +
  theme(axis.title   = element_text(face = "bold"),
        axis.text    = element_text(face = "bold"),
        plot.caption = element_text(hjust = 0)) +
    ylab("Least square mean\nbrant count") +
  ggtitle ("Brant counts",
           subtitle = "In six Sample Periods") +
  labs(caption  = paste0("\nBrant counts for six Sample Periods. ", 
                         "Boxes indicate the LS mean. \n",
                         "Error bars indicate the 95% ",
                         "confidence interval of the LS mean. \n",
                         "Means sharing a letter are not ",
                         "significantly different (Tukey-adjusted \n",
                         "comparisons)."),
       hjust=0.5) +
  geom_text(nudge_x = c(0, 0, 0, 0),
            nudge_y = c(4, 4, 4, 4),
            color   = "black")+
  scale_color_manual(values = c("blue", "red"))

Results in this: 

SamplePer.jpeg



BUT, when I try to do this for an interaction term, with this code: 
Plot_WaterDepth = lsmeans(test5, ~ PlotType | WaterDepth) 
Plot_WaterDepth = cld(Plot_WaterDepth, alpha=0.10, Letters=letters, adjust="tukey")
Plot_WaterDepth$PlotType = factor(Plot_WaterDepth$PlotType,
                                  levels=c("Control","Not planted","Narrow cultch"))
Plot_WaterDepth$.group=gsub(" ", "", Plot_WaterDepth$.group)

And try to plot with this: 
Plot_WaterDepth$PlotType = factor(Plot_WaterDepth$PlotType,
                                  levels=c("Control","Not planted","Narrow cultch"))
Plot_WaterDepth$.group=gsub(" ", "", Plot_WaterDepth$.group)
pd = position_dodge(0.4)
ggplot(Plot_WaterDepth,
       aes(x     = WaterDepth,
           y     = lsmean,
           color = PlotType,
           label = .group)) +
  geom_point(shape  = 15,
             size   = 4,
             position = pd) +
  geom_errorbar(aes(ymin  =  asymp.LCL,
                    ymax  =  asymp.UCL),
                width =  0.2,
                size  =  0.7,
                position = pd) +
  theme_bw() +
  theme(axis.title   = element_text(face = "bold"),
        axis.text    = element_text(face = "bold"),
        plot.caption = element_text(hjust = 0)) +
  ylab("Least square mean\nbrant count") +
  ggtitle ("Brant counts",
           subtitle = "In three Water Depths") +
  labs(caption  = paste0("\nBrant counts at three Water Depths. ", 
                         "Boxes indicate the LS mean. \n",
                         "Error bars indicate the 95% ",
                         "confidence interval of the LS mean. \n",
                         "Means sharing a letter are not ",
                         "significantly different (Tukey-adjusted \n",
                         "comparisons)."),
       hjust=0.5) +
  geom_text(nudge_x = c(0, 0, 0, 0),
            nudge_y = c(4, 4, 4, 4),
            color   = "black")+ #HERE IS WHERE THINGS GO WRONG.
  scale_color_manual(values = c("blue", "red", "green"))

I get this: 

Plot_WaterDepth.jpeg


As you can probably imagine, this don't look like I am  hoping, which is that my labels are the letters showing significant differences (named ".group") being above their associated/respective plot types within each Water Depth. I have spent hours and hours trying out a variety of different options, none of which have worked and most of which have produced something rather visually funky (great for entertainment, less so for papers). I know it is only telling me to do what I tell it to do, but I am having difficulty understanding how to map the desired aesthetics to the the desired locations on the figure. Any help would be greatly appreciated! 


Thank you so much! 
SamplePer.tiff
Plot_WaterDepth.tiff

Dan Hicks

unread,
Sep 21, 2018, 12:15:20 AM9/21/18
to davi...@googlegroups.com
Hello, 

I think you need to dodge the text labels. 

But it's difficult to be sure, because you've included a lot of extraneous details and haven't given us a machine-readabke dataset that we can use with your code. You might read up on how to create a minimal working example (MWE): https://stackoverflow.com/help/mcve

Cheers, 
Dan

--
Check out our R resources at http://d-rug.github.io/
---
You received this message because you are subscribed to the Google Groups "Davis R Users' Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to davis-rug+...@googlegroups.com.
Visit this group at https://groups.google.com/group/davis-rug.
For more options, visit https://groups.google.com/d/optout.

kw...@harveyecology.com

unread,
Sep 21, 2018, 12:59:53 AM9/21/18
to Davis R Users' Group
Thanks Dan, I have tried streamlining here. I have tried position dodge, which doesn't change the outcome. 

Here is a revision of the original message: 
 
I am trying to add the labels for significant differences between combinations of two factors, and am having some difficulties. 

I have a negative binomial mixed model with multiple nesting levels and random factors, with a count response. All of my predictors are categorical. I chose my final model and ran this through lsmeans() and cld() to do pairwise comparisons for significant factors and interactions. 

When I have one factor with any number of levels, my code works fine. 
For example (where test5 is my glmm, and SamplePer is the factor of interest): 

SamplePer = lsmeans(test5, ~ SamplePer) 
SamplePer = cld(SamplePer, alpha=0.10, Letters=letters, adjust="tukey")

Which gives an object of type 'summary_emm' and 'data.frame' looking like this: 
 SamplePer     lsmean        SE df  asymp.LCL asymp.UCL .group
 Apr1       -0.4863283 0.2632676 NA -1.1789954 0.2063388 a     
 Mar2       0.1105724 0.2221710 NA -0.4739680 0.6951129 ab    
 Mar1       0.4999976 0.2771670 NA -0.2292395 1.2292346 b     
 Feb2       0.8025046 0.2814722 NA  0.0619406 1.5430687 bc    
 Feb1       1.5699948 0.2515543 NA  0.9081458 2.2318437 cd    
 Jan         1.8281466 0.2520075 NA  1.1651054 2.4911879 d     

I have included this as a dataframe (SamplePer.csv).  

Let's not even get into the topic of p-values please, I know. LOL. Anyway.

###  Plot 
ggplot(SamplePer,
       aes(x     = SamplePer,
              y     = lsmean,
              label = .group)) +
  geom_point(shape  = 15,
             size   = 4,
             position = pd) +
  geom_errorbar(aes(ymin  =  asymp.LCL,
                    ymax  =  asymp.UCL),
                width =  0.2,
                size  =  0.7,
                position = position_dodge(0.4)) +
  geom_text(nudge_x = c(0, 0, 0, 0), 
            nudge_y = c(4, 4, 4, 4),
            color   = "black")+
  scale_color_manual(values = c("blue", "red"))

Results in the attached .tiff file "SamplerPer". 


BUT, when I try to do this for an interaction term, with this code: 
Plot_WaterDepth = lsmeans(test5, ~ PlotType | WaterDepth) 
Plot_WaterDepth = cld(Plot_WaterDepth, alpha=0.10, Letters=letters, adjust="tukey")

And try to plot with this: 
ggplot(Plot_WaterDepth,
       aes(x     = WaterDepth,
           y     = lsmean,
           color = PlotType,
           label = .group)) +
  geom_point(shape  = 15,
             size   = 4,
             position = pd) +
  geom_errorbar(aes(ymin  =  asymp.LCL,
                    ymax  =  asymp.UCL),
                width =  0.2,
                size  =  0.7,
                position = position_dodge(0.4)) +
  geom_text(nudge_x = c(0, 0, 0, 0),
            nudge_y = c(4, 4, 4, 4),
            color   = "black")+ #HERE IS WHERE THINGS GO WRONG.
  scale_color_manual(values = c("blue", "red", "green"))

I get the attached "Plot.WaterDepth" jpeg. 


As you can probably imagine, this doesn't look like I was hoping it would, which is that my labels would be the letters showing significant differences (named ".group") being above their associated/respective plot types within each Water Depth. I have spent hours trying out a variety of different options, none of which have worked and most of which have produced something rather visually funky (great for entertainment, less so for papers). I know it is only telling me to do what I tell it to do, but I am having difficulty understanding how to map the desired aesthetics to the the desired locations on the figure. Any help would be greatly appreciated! 


Thank you so much! I hope this post is more readable. Thanks. 
SamplePer.csv
SamplerPer.tiff
Plot_WaterDepth.csv
Plot_WaterDepth.tiff

Rosemary Hartman

unread,
Sep 21, 2018, 6:56:02 AM9/21/18
to davi...@googlegroups.com
I think you need to play with the "nudge_x" values in your text geom. Try:
geom_text(nudge_x = c(-.2, 0, 0.2, -.2,0,.2,-.2,0,.2),
            nudge_y = c(4, 4, 4),
            color   = "black")

--
Check out our R resources at http://d-rug.github.io/
---
You received this message because you are subscribed to the Google Groups "Davis R Users' Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to davis-rug+...@googlegroups.com.
Visit this group at https://groups.google.com/group/davis-rug.
For more options, visit https://groups.google.com/d/optout.


--

Daniel Hicks

unread,
Sep 21, 2018, 1:30:34 PM9/21/18
to davi...@googlegroups.com
You can’t use both nudge and dodge.  The easiest way to get the vertical alignment you want is to use dodge.  So then you have to set the label height by passing a new y aesthetic.  If you also override the color aesthetic, you need to include a group aesthetic so that ggplot understands how to dodge the labels.  

Here’s a MWE.  

library(ggplot2)

## Load data ----
Plot_WaterDepth = read.csv('Plot_WaterDepth.csv')
## For solution 2, y position of the labels
Plot_WaterDepth$label_y = Plot_WaterDepth$lsmean + 1

## Define underlying plot, w/out labels ----
dodge = position_dodge(width = .5)

basic_plot = ggplot(Plot_WaterDepth,
       aes(x     = WaterDepth,
           y     = lsmean,
           group = PlotType,
           color = PlotType,
           label = .group)) +
    geom_errorbar(aes(ymin  =  asymp.LCL,
                      ymax  =  asymp.UCL),
                  position = dodge)

## Solution 1 ----
## Labels at a fixed height
basic_plot +
    geom_text(aes(y = 4), color = 'black', position = dodge)

## Solution 2 ----
## Labels at variable height, relative to corresponding values
basic_plot +
    geom_text(aes(y = label_y), color = 'black', position = dodge)

----
Daniel J. Hicks
Postdoctoral Researcher
Data Science Initiative
University of California, Davis

"Cautious, careful people, always casting about to preserve their reputation and social standing, never can bring about a reform. Those who are really in earnest must be willing to be anything or nothing in the world's estimation." -- Susan B. Anthony

Pronouns: Masculine (he/him/his) or neutral (they/them/their)
Reply all
Reply to author
Forward
0 new messages