ggplot2 specify geom_text position by conventional “top”, “bottom”, “left”, “right”, “center”

夙愿已清 提交于 2019-12-06 14:29:23

问题


I'm making some graphs in ggplot and cannot figure out how to plot in graph text without specifying x and y positions.

Lets say I'm making a graph like this.

sp <- ggplot(mpg, aes(hwy, cty, label = "sometext"))+
    geom_point()

I want to add the label to be printed in the same way in every graph. Calling the following simply prints text at every x, y value supplied to aes.

sp + geom_text()

I could manipulate the x y data supplied to geom_text() to ensure that the text remained in the same relative position between graphs but is there not a simply way to call position by default positions like "top", "bottom" etc? I.e. sp + geom_text(position="top").


回答1:


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)




回答2:


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)



回答3:


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   




回答4:


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, ...))
}


来源:https://stackoverflow.com/questions/47916307/ggplot2-specify-geom-text-position-by-conventional-top-bottom-left-rig

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!