Specify position of geom_text by keywords like “top”, “bottom”, “left”, “right”, “center”

后端 未结 5 1368
名媛妹妹
名媛妹妹 2020-12-31 23:37

I wish to position text in a ggplot without specifying x and y positions, but instead using keywords, like e.g. in graphics::leg

相关标签:
5条回答
  • 2020-12-31 23:51

    It's certainly possible to write a wrapper but the way units and justification are defined makes it rather verbose,

    library(ggplot2)
    
    qplot(1,1) + 
      annotation_compass('testN') + 
      annotation_compass('testE','E') + 
      annotation_compass('testSW','SW') + 
      annotation_compass('testW','W')
    

    annotation_compass <- function(label,
                                   position = c('N','NE','E','SE','S','SW','W','NW'),
                                   padding = grid::unit(c(0.5,0.5),"line"), ...){
      position <- match.arg(position)
      x <- switch (position,
        N = 0.5,
        NE = 1,
        E = 1,
        SE = 1,
        S = 0.5, 
        SW = 0,
        W = 0, 
        NW = 0
      )
      y <- switch (position,
                   N = 1,
                   NE = 1,
                   E = 0.5,
                   SE = 0,
                   S = 0, 
                   SW = 0,
                   W = 0.5, 
                   NW = 1
      )
      hjust <- switch (position,
                   N = 0.5,
                   NE = 1,
                   E = 1,
                   SE = 1,
                   S = 0.5, 
                   SW = 0,
                   W = 0, 
                   NW = 0
      )
      vjust <- switch (position,
                   N = 1,
                   NE = 1,
                   E = 0.5,
                   SE = 0,
                   S = 0, 
                   SW = 0,
                   W = 0.5, 
                   NW = 1
      )
      f1 <- switch (position,
                       N = 0,
                       NE = -1,
                       E = -1,
                       SE = -1,
                       S = 0, 
                       SW = 1,
                       W = 1, 
                       NW = 1
      )
      f2 <- switch (position,
                       N = -1,
                       NE = -1,
                       E = 0,
                       SE = 1,
                       S = 1, 
                       SW = 1,
                       W = 0, 
                       NW = -1
      )
      annotation_custom(grid::textGrob(label, 
                                       x=grid::unit(x,"npc") + f1*padding[1] , 
                                       y=grid::unit(y,"npc") + f2*padding[2],
                                       hjust=hjust,vjust=vjust, ...))
    }
    
    0 讨论(0)
  • 2020-12-31 23:56

    geom_text wants to plot labels based on your data set. It sounds like you're looking to add a single piece of text to your plot, in which case, annotate is the better option. To force the label to appear in the same position regardless of the units in the plot, you can take advantage of Inf values:

    sp <- ggplot(mpg, aes(hwy, cty, label = "sometext"))+
      geom_point() +
      annotate(geom = 'text', label = 'sometext', x = -Inf, y = Inf, hjust = 0, vjust = 1)
    print(sp)
    

    0 讨论(0)
  • 2021-01-01 00:03

    I avoid annotate like the plague and just use an empty data frame data argument for geom_text:

    ggplot(mpg, aes(hwy, cty, label = "sometext"))+
      geom_point() +
      geom_text(data=data.frame(), aes(label = 'sometext', x = -Inf, y = Inf),
                hjust = 0, vjust = 1)
    
    0 讨论(0)
  • 2021-01-01 00:04

    The solution using infinity is good and is definitely the easiest option.

    However, if you want more control over the position of your labels (for example, if you want them centered, or if you want more space between the axis line and annotation), you can use some math with min() and max() of your plot titles to create centered titles at top, bottom, right, or left. The code below is a bit lengthy, but will still place labels correctly if the values in your plot change. Also, to copy to other plots, you won't need to manually calculate values, just change the names of the x and y variables.

    sp <- ggplot(mpg, aes(hwy, cty)) +
      geom_point() +
      theme_classic() +
      annotate("text", label = "top", 
               x = 0.5*(min(mpg$hwy) + max(mpg$hwy)), y = max(mpg$cty), vjust = 1) +
      annotate("text", label = "bottom", 
               x = 0.5*(min(mpg$hwy) + max(mpg$hwy)), y = min(mpg$cty), vjust = 0) +
      annotate("text", label = "right", 
               x =  max(mpg$hwy), y = 0.5*(min(mpg$cty) + max(mpg$cty)), hjust = 1) +
      annotate("text", label = "left", 
                x =  min(mpg$hwy), y = 0.5*(min(mpg$cty) + max(mpg$cty)), hjust = 0)
    
    sp   
    

    0 讨论(0)
  • 2021-01-01 00:06

    In ggpmisc::geom_text_npc the x and y positions are given in npc units (0-1). However, the positions can also be specified as "words":

    d = data.frame(x = rep(c("left", "center", "right"), each = 3),
                   y = rep(c("bottom", "middle", "top"), 3))
    d$lab = with(d, paste0(x, "-", y))
    d
    #        x      y           lab
    # 1   left bottom   left-bottom
    # 2   left middle   left-middle
    # 3   left    top      left-top
    # 4 center bottom center-bottom
    # 5 center middle center-middle
    # 6 center    top    center-top
    # 7  right bottom  right-bottom
    # 8  right middle  right-middle
    # 9  right    top     right-top
    
    ggplot(d) +
      geom_text_npc(aes(npcx = x.chr, npcy = y.chr, label = lab))
    

    0 讨论(0)
提交回复
热议问题