2
votes

I'm also having some trouble with annotating text to individual facets in ggplot2 (w/ reference to related post: Annotating text on individual facet in ggplot2).

Data frame:

str(cfit_2)
'data.frame':   186 obs. of  5 variables:
 $ Participant: Factor w/ 31 levels "2","3","4","5",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Condition  : Factor w/ 2 levels "Active control group",..: 1 2 2 2 1 1 2 2 1 1 ...
 $ Time       : Factor w/ 2 levels "Pretest","Posttest": 1 1 1 1 1 1 1 1 1 1 ...
 $ CFIT       : num  10 13 17 11 19 15 19 11 15 16 ...
 $ Version    : Factor w/ 3 levels "Total CFIT","CFIT version 1",..: 1 1 1 1 1 1 1 1 1 1 ...

Code:

p<-ggplot(cfit_2,aes(Time,CFIT,fill=Condition))+
  scale_y_continuous(breaks=1:20)+
  scale_fill_manual(values=c("white","lightgrey"))+
  geom_violin()+
  theme_classic()+
  coord_cartesian(ylim=c(1, 20),xlim=c(1, 2))+
  theme(axis.line=element_blank())+
  facet_grid(.~Version)+ylab("CFIT raw score")+

  geom_segment(x=.3925,xend=.3925,y=1,yend=20)+
  geom_segment(x=1,xend=2,y=.015,yend=.015)+

 stat_summary(fun.y=mean,geom="point",position=position_dodge(w=.9))+
 stat_summary(fun.data=mean_cl_boot,geom="errorbar",position=position_dodge(w=.9),width=0)+

   geom_segment(data=data.segm_1,aes(x=x,xend=xend,y=y,yend=yend),inherit.aes=FALSE)+
   geom_segment(data=data.segm_2,aes(x=x,xend=xend,y=y,yend=yend),inherit.aes=FALSE)+
   geom_segment(data=data.segm_3,aes(x=x,xend=xend,y=y,yend=yend),inherit.aes=FALSE)+
   geom_segment(data=data.segm_1_2,aes(x=x,xend=xend,y=y,yend=yend),inherit.aes=FALSE)+
   geom_segment(data=data.segm_2_2,aes(x=x,xend=xend,y=y,yend=yend),inherit.aes=FALSE)+
   geom_segment(data=data.segm_3_2,aes(x=x,xend=xend,y=y,yend=yend),inherit.aes=FALSE)

Violin plot

What I want to do is to add "NS" or "*" next to every segment. Using the following data frame:

ann_text<-data.frame(Time=c("Pretest","Posttest","Pretest","Posttest","Pretest","Posttest"),CFIT=c(8,7,3,2,2,3),
       lab=c("NS","*","NS","*","NS","*"),
       Version=factor(c("Total CFIT","Total CFIT","CFIT version 1","CFIT version 1","CFIT version 2","CFIT version 2"),
                levels=c("Total CFIT","CFIT version 1","CFIT version 2")))

ann_text:

Time CFIT lab        Version
1  Pretest    8  NS     Total CFIT
2 Posttest    7   *     Total CFIT
3  Pretest    3  NS CFIT version 1
4 Posttest    2   * CFIT version 1
5  Pretest    2  NS CFIT version 2
6 Posttest    3   * CFIT version 2

... I get the following result from p+geom_text(data=ann_text,aes(label=lab)):

**Error in eval(expr, envir, enclos) : object 'Condition' not found**

Moving aes(fill=Condition) to geom_violin() gives the following plot:

Violin plot #2

1
Any variable used in the global setting of aes is passed down to all other layers. So in this case, it is probably better to move fill=Condition to geom_violin() - Heroka
Thanks @Heroka! That works fine, except now I'm having trouble with the stat_summary(fun.data=mean_cl_boot,geom="errorbar",position=position_dodge(w=.9),width=0; above). - Eric Per Anders Karlsson
Hm. I didn't see all of your code due to the formatting (and I can't do a quick tinker myself as your q is not reproducible), but you could use override.aes. As an aside, you could consider combining data to create all your segments, creates cleaner and easier code. - Heroka

1 Answers

5
votes

The easiest way is to tell geom_text to not use Condition for the fill, by setting it to NULL. This way, you can keep fill in the ggplot call and have it applied to all other geoms, without the need to specify it each time.

Create data (since you didn't supply any)

cfit_2 <- data.frame(
  Time = c('Pretest', 'Posttest'),
  Condition = rep(c('Active control group', 'Training group'), each = 2),
  Version = rep(c('Total CFIT', 'CFIT version 1', 'CFIT version 2'), each = 40),
  CFIT = rnorm(120, 10, 3)
)

Use your plotting code

p<-ggplot(cfit_2,aes(Time,CFIT,fill=Condition))+
  #scale_y_continuous(breaks=1:20)+
  scale_fill_manual(values=c("white","lightgrey"))+
  geom_violin()+
  theme_classic()+
  #coord_cartesian(ylim=c(1, 20),xlim=c(1, 2))+
  theme(axis.line=element_blank())+
  facet_grid(.~Version)+ylab("CFIT raw score")+

  geom_segment(x=.3925,xend=.3925,y=1,yend=20)+
  geom_segment(x=1,xend=2,y=.015,yend=.015)+

  stat_summary(fun.y=mean,geom="point",position=position_dodge(w=.9))+
  stat_summary(fun.data=mean_cl_boot,geom="errorbar",position=position_dodge(w=.9),width=0)

(Note that I commented out two lines about the axes, since they were giving me troubles. I also removed the annotated lines, since you didn't supply data for those.)

Add the text

First create the coordinates where you want the asterisks and "NS"es.

ann_text<-read.table(text="
Time CFIT lab        Version
Pretest    15  NS     'Total CFIT'
Posttest    7   *     'Total CFIT'
Pretest    3  NS 'CFIT version 1'
Posttest    2   * 'CFIT version 1'
Pretest    2  NS 'CFIT version 2'
Posttest    3   * 'CFIT version 2'
",header=T)

Then annotate.

p + geom_text(data = ann_text, aes(label = lab, fill = NULL))

Result

enter image description here

Of course, the text doesn't look that nice (it's at the wrong y level), but that is because my data is different.