将y轴标题放在图表的左上角

时间:2014-03-19 16:23:57

标签: r ggplot2

我在R中绘制了一个带ggplot2的图,我希望y轴的标题出现在图的左上角。请考虑以下代码以获取默认行为:

require(ggplot2)

xy = data.frame(x=1:10, y=10:1)

ggplot(data = xy) +
  geom_point(aes(x = x, y = y)) +
  ylab("very long label")

这会生成以下图表:

Original graph

我想移动并旋转文本“非常长的标签”。我可以使用theme()函数来做一些事情:

ggplot(data = xy) +
  geom_point(aes(x = x, y = y)) +
  ylab("very long label") +
  theme(axis.title.y = element_text(angle = 0, vjust = 1.1, hjust = 10))

这给了我这个:

modified graph

您可以看到我的目的地,但边距不正确 - 左边距太大,因为空间是为旋转标签保留的,而上边距对于文字来说太小了。

如何告诉ggplot我希望y轴标题在该位置没有旋转并让它为它保留适当的空间?

2 个答案:

答案 0 :(得分:6)

将它放在主图标题中:

ggplot(data = xy) +
  geom_point(aes(x = x, y = y)) +
  ggtitle("very long label") +
  theme(plot.title = element_text(hjust = 0))

如果你喜欢使用负hjust值,你可以将它稍微向左推,但如果你走得太远,标签将被剪裁。在这种情况下,您可以尝试使用plot.margin

ggplot(data = xy) +
  geom_point(aes(x = x, y = y)) +
  ggtitle("very long label") +
  theme(plot.title = element_text(hjust = -0.3),
        plot.margin = rep(grid::unit(0.75,"in"),4))

很明显,这使得向图表添加实际标题变得很困难。您始终可以使用以下内容手动注释:

grid.text("Actual Title",y = unit(0.95,"npc"))

或者反过来,使用grid.text作为y标签。

答案 1 :(得分:1)

我刚刚遇到了同样的问题,并找到了对社区有用的解决方案。

这个想法是创建一个自定义主题,用副标题替换轴标签。下面以示例为例:

p <- ggplot2::ggplot(iris, ggplot2::aes(x = Sepal.Width, y = Sepal.Length,
                                        color = Species)) +
  ggplot2::geom_point()

极简解决方案

创建一个类mytheme,该类可以修改ggplot使用的主题。在此,在极简解决方案中,不对样式进行任何限制(我将在稍后介绍限制)。

custom_theme <- function(...){
  out <- ggplot2::theme_minimal() + ggplot2::theme(...)
  class(out) <- c("mytheme",class(ggplot2::theme_minimal()))
  return(out)
}

与此类相关联的ggplot_add方法将覆盖默认方法。此自定义方法采用现有的y标签并将其放入subtitle中。在函数的前两行进行替换。函数的第三行使用稍后定义的update_theme函数:

ggplot_add.mytheme <- function(object, plot, object_name) {

  plot$labels$subtitle <- plot$labels$y
  plot$labels$y <- NULL
  plot$theme <- update_theme(plot$theme, object)
  plot
}

update_theme函数是ggplot2软件包的一部分,直到最近。该功能最近消失了(see this commit)。我实现的技巧是这样定义函数:

update_theme <- function(oldtheme, newtheme) {

  # If the newtheme is a complete one, don't bother searching
  # the default theme -- just replace everything with newtheme
  if (isTRUE(attr(newtheme, "complete", exact = TRUE)))
    return(newtheme)

  # These are elements in newtheme that aren't already set in oldtheme.
  # They will be pulled from the default theme.
  newitems <- !names(newtheme) %in% names(oldtheme)
  newitem_names <- names(newtheme)[newitems]
  oldtheme[newitem_names] <- theme_get()[newitem_names]

  # Update the theme elements with the things from newtheme
  # Turn the 'theme' list into a proper theme object first, and preserve
  # the 'complete' attribute. It's possible that oldtheme is an empty
  # list, and in that case, set complete to FALSE.
  old.validate <- isTRUE(attr(oldtheme, "validate"))
  new.validate <- isTRUE(attr(newtheme, "validate"))
  oldtheme <- do.call(theme, c(oldtheme,
                               complete = isTRUE(attr(oldtheme, "complete")),
                               validate = old.validate & new.validate))

  oldtheme + newtheme
}

然后可以使用theme创建预期的输出:

p + ggplot2::labs(y = "A very very long label") + custom_theme() 

enter image description here

限制

轴样式元素未报告为字幕

如果以后要更改轴标题的某些样式元素(例如,文本大小),则 y 标签将是一个问题,因为它是字幕元素。例如,运行的用户

p + custom_theme(axis.title = ggplot2::element_text(size = 24)) 

enter image description here

希望 y 标签的尺寸也为24。我认为这不是一个真正的问题,因为您可以更改custom_theme并增加约束条件

在调用labs后设置theme

如果用户在更改theme之前设置labs,例如,

p + ggplot2::labs(y = "A very very long label") + custom_theme()  + ggplot2::labs(y = "override")

enter image description here