Search code examples
rggplot2

Putting label in Histogram in ggplot


I have below histogra musing ggplot

library(ggplot2)
n = 1000
mean = 0
sd = 1
binwidth = 0.3 # passed to geom_histogram and stat_function
set.seed(1)
df <- data.frame(x = rnorm(n, mean, sd))

myplot = ggplot(df, aes(x = x, mean = mean, sd = sd, binwidth = binwidth, n = n)) +
    theme_bw() +
    geom_histogram(binwidth = binwidth, 
        colour = "white", fill = "cornflowerblue", size = 0.1)

Now I want to add one custom label at the top-middl area, but there should be some margin, say 10 points at the top of my label. I tried below

myplot+
geom_label(aes(x = mean((df$x)), y = 100), label = 'Plot with y', label.padding = unit(.7, 'lines'), fill = '#000000', color = '#ffffff', alpha = 0.2)

Is there any way to dynamically (based on data only without any hardcoding) set y = 100 to keep the label at the top with 10 points margin?


Solution

  • One option to place your label at the top of the plot area and having some margin would be to use annotation_custom which requires to add your label via a grob. For the latter I use gridtext::richtext_grob (as grid does not provide a labelGrob whereas ggplot2 does not export it):

    library(ggplot2)
    library(gridtext)
    library(grid)
    
    myplot +
      annotation_custom(
        grob = gridtext::richtext_grob(
          text = "Plot with y",
          # Place at the top with margin of 5mm
          y = unit(1, "npc") - unit(5, "mm"),
          # Padding around label
          padding = unit(.7, "lines"),
          gp = grid::gpar(col = "#ffffff"),
          box_gp = grid::gpar(fill = "#000000", alpha = .6),
          vjust = 1
        ),
        xmin = mean(df$x),
        xmax = mean(df$x)
      )
    

    EDIT If you can't install any non-standard package (e.g. gridtext) one option would be to use the non-exported labelGrob from ggplot2 using ::::

    myplot +
      annotation_custom(
        grob = ggplot2:::labelGrob(
          label = "Plot with y",
          # Place at the top with margin of 5mm
          y = unit(1, "npc") - unit(5, "mm"),
          # Padding around label
          padding = unit(rep(.7, 4), "lines"),
          text.gp = grid::gpar(col = "#ffffff"),
          rect.gp = grid::gpar(fill = "black", alpha = .6),
          just = "top"
        ),
        xmin = mean(df$x),
        xmax = mean(df$x)
      )