0

How can I insert annotations outside the plot?

I want to add a note on top of the first bar to signal that it continues e.g. up to 1000. If I use annotate, the note won't go outside the plot. (Note that I am using coord_cartesian to limit the y axis to 100.)

Here is my code.

plot <- ggplot() +
  geom_crossbar(data=GHG, aes(x=Study, y=Avg, ymin=Min, ymax=Max), 
                fill="white", width=0.3) +
  coord_cartesian(ylim=c(0, 100), clip="off") +
  labs(x="", y="g CO2-eq.") +
  annotate("text", x=1, y=150, label=c("150"), vjust=-1) +
  theme(legend.position = "bottom",
        axis.text.x = element_text(angle=0, vjust=1, hjust=0.5),
        panel.grid.major.x= element_blank(),
        panel.grid.minor = element_blank(),
        plot.margin = unit(c(1,3,1,1),"lines"))

And here is the chart:

enter image description here

Z.Lin
  • 28,055
  • 6
  • 54
  • 94
brezen
  • 11
  • 2
  • Are you sure it's not because your annotation's y position is too far beyond the chart's dimensions? Does this persist if you change it to `annotate("text", x=1, y=105, ...)`? – Z.Lin Mar 08 '19 at 04:37
  • Yes, everything that goes beyond the limits of the chart (1,100) is cut out. – brezen Mar 08 '19 at 11:27

1 Answers1

2

One strategy is to use a secondary axis and the labels to annotate your bar. This is a bit tricky, because only continuous scales can have a secondary axis.

I used the following data.frame for test purpose:

GHG <- data.frame(Avg = c(50, 37, 62), Min = c(10, 25, 25), Max = c(1000, 50, 80), Study = c("A", "B", "C"))

The code:

ggplot() +
  geom_crossbar(data=GHG, aes(x=as.numeric(Study), y=Avg, ymin=Min, ymax=Max), 
                fill="white", width=0.3) +
  coord_cartesian(ylim=c(0, 100), clip = "on") +

  scale_x_continuous(position = "top",
                     breaks = 1:length(unique(GHG$Study)),
                     labels = c(1000, rep("", length(unique(GHG$Study)) - 1)),
                     sec.axis = sec_axis(~.,
                                         breaks = 1:length(unique(GHG$Study)),
                                         labels = rep("", length(unique(GHG$Study))))) +

  labs(x="", y="g CO2-eq.") +
  theme(legend.position = "bottom",
        axis.text.x = element_text(angle=0, vjust=1, hjust=0.5),
        panel.grid.major.x= element_blank(),
        panel.grid.minor = element_blank(),
        plot.margin = unit(c(1,3,1,1),"lines"),

        axis.ticks.x.top = element_blank(),
        axis.text.x.top = element_text(size = 14, color = "black", margin = margin(b = 5)))

Plot

Details:

The aes is slightly changed to allow for continuous scale: aes(x=as.numeric(Study), y=Avg, ymin=Min, ymax=Max)

In coord_cartesian(ylim=c(0, 100), clip = "on"): clip is set to on to clip the part of the bars that goes out of the plot area.

Add and configure the continuous scale for X on top: scale_x_continuous(position = "top",

Manually add breaks for each value of Study: breaks = 1:length(unique(GHG$Study)),

Label the first break with the text you want to add, the rest of the breaks has no text: labels = c("text", rep("", length(unique(GHG$Study)) - 1)),

Add a secondary axis to keep the ticks at the bottom. If you don't want them, this is not necessary: sec.axis = sec_axis(~.,

Manually set the breaks for the continuous scale: breaks = 1:length(unique(GHG$Study)),

And add blank labels to reproduce your example: labels = rep("", length(unique(GHG$Study))))) +

In the theme method, remove the ticks for the top axis: axis.ticks.x.top = element_blank(),

And finally customize the font, color and everything for the top label: axis.text.x.top = element_text(size = 14, color = "black", margin = margin(b = 5)))

Slagt
  • 589
  • 2
  • 10