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

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, ...)? Commented Mar 8, 2019 at 4:37
  • Yes, everything that goes beyond the limits of the chart (1,100) is cut out. Commented Mar 8, 2019 at 11:27

1 Answer 1

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)))

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.