在ggplot2中旋转和调整坐标轴标签的间距

894

我有一个绘图,其中 x 轴是一个标签很长的因子。虽然这可能不是一种理想的可视化方式,但目前我只想将这些标签旋转成垂直方向。我已经通过下面的代码解决了这个问题,但是可以看到,标签并没有完全可见。

data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))
q <- qplot(cut,carat,data=diamonds,geom="boxplot")
q + opts(axis.text.x=theme_text(angle=-90))

这里输入图片描述


8
现在ggplot 3.3.0已经发布,我认为被接受的答案应该改为jan-glx的答案。 - akraf
9个回答

1493
将最后一行更改为:
q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

默认情况下,即使旋转文本,轴也会对齐在文本的中心。但是当你旋转正负90度时,通常希望它对齐在边缘而不是中心:

alt text

上面的图片来自这篇博客文章


121
在最新版本的ggplot2中,命令应该是:`q + theme(axis.text.x=element_text(angle=-90, hjust=0))`(说明:这是一种R语言的代码,用于旋转x轴标签。在新版本中,使用上述命令可以实现此功能。我将其翻译成了通俗易懂的中文,但没有改变其原意,并且没有提供任何额外的解释或内容。) - rnorberg
63
对于那些发现hjust没有按照这里描述的行为的人,请尝试使用 theme(axis.text.x=element_text(angle = 90, vjust = 0.5))。从ggplot2 0.9.3.1版本开始,这似乎是解决方案。 - lilster
46
为了正确对齐标签,我实际上需要将上述两个方案结合起来使用:q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) - jupp0r
40
@jupp0r是正确的。theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))目前是有效的。 - user1685185
70
如果您希望标签以45度旋转(更易读取),则theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))会产生良好的结果。 - jan-glx
显示剩余5条评论

156

ggplot 3.3.0通过提供guide_axis(angle = 90)(作为scale_..guide参数或guidesx参数)来解决了这个问题:

library(ggplot2)
data(diamonds)
diamonds$cut <- paste("Super Dee-Duper", as.character(diamonds$cut))

ggplot(diamonds, aes(cut, carat)) +
  geom_boxplot() +
  scale_x_discrete(guide = guide_axis(angle = 90)) +
  # ... or, equivalently:
  # guides(x =  guide_axis(angle = 90)) +
  NULL

来自angle参数的文档

与在theme() / element_text()中设置角度相比,这也使用一些启发式方法自动选择您可能想要的hjust和vjust。


或者,它还提供了 guide_axis(n.dodge = 2)(作为scale_..guide参数或作为guidesx参数)来通过垂直闪避标签来解决过度绘制问题。 在这种情况下,它运行得非常好:

library(ggplot2)
data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))

ggplot(diamonds, aes(cut, carat)) + 
  geom_boxplot() +
  scale_x_discrete(guide = guide_axis(n.dodge = 2)) +
  NULL


4
虽然我喜欢这里的躲避解决方案,但值得注意的是,guide_axis(angle=90)会选择正确的vjust和hjust值,从而解决了OP中的问题。 - eipi10
1
@eipi10 谢谢,我之前不知道,现在已经添加到答案里了! - jan-glx
1
不幸的是,这个解决方案与ggplotly函数不兼容,因为旋转的轴标签没有被保留。只有之前的theme()解决方案可以与ggplotly一起使用。 - Olivier
@Olivier 是的,plotly.Rggplotly 只支持 ggplot 的功能子集。这个问题 提供了一个解决方法来避免重叠。 - jan-glx

142

使用 coord_flip()

data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))

qplot(cut, carat, data = diamonds, geom = "boxplot") +
  coord_flip()

enter image description here


添加 str_wrap()

# wrap text to no more than 15 spaces
library(stringr)
diamonds$cut2 <- str_wrap(diamonds$cut, width = 15)
qplot(cut2, carat, data = diamonds, geom = "boxplot") +
  coord_flip()

enter image description here


R数据科学的第3.9章中,Wickham和Grolemund回答了这个问题:

coord_flip()可以交换x轴和y轴。这很有用(例如),如果你想要水平的箱线图。对于长标签也很有用:很难让它们适合x轴而不重叠。


105
为使刻度标签上的文本完全可见并与y轴标签读取方向一致,将最后一行更改为:
q + theme(axis.text.x=element_text(angle=90, hjust=1))

33

我想提供一种替代方案,类似于我即将提出的方案所需的强大解决方案在最新版本的ggtern中也是必需的,因为引入了画布旋转功能。

基本上,您需要使用三角函数确定相对位置,通过构建一个函数来返回element_text对象,该函数给定角度(即度数)和定位信息(即x、y、top或right之一)。

#Load Required Libraries
library(ggplot2)
library(gridExtra)

#Build Function to Return Element Text Object
rotatedAxisElementText = function(angle,position='x'){
  angle     = angle[1]; 
  position  = position[1]
  positions = list(x=0,y=90,top=180,right=270)
  if(!position %in% names(positions))
    stop(sprintf("'position' must be one of [%s]",paste(names(positions),collapse=", ")),call.=FALSE)
  if(!is.numeric(angle))
    stop("'angle' must be numeric",call.=FALSE)
  rads  = (angle - positions[[ position ]])*pi/180
  hjust = 0.5*(1 - sin(rads))
  vjust = 0.5*(1 + cos(rads))
  element_text(angle=angle,vjust=vjust,hjust=hjust)
}

说实话,在我看来,我认为在ggplot2hjustvjust参数中应该加入一个“自动”选项,在指定角度时可以使用,不管怎样,让我们演示一下上面的方法。

#Demonstrate Usage for a Variety of Rotations
df    = data.frame(x=0.5,y=0.5)
plots = lapply(seq(0,90,length.out=4),function(a){
  ggplot(df,aes(x,y)) + 
    geom_point() + 
    theme(axis.text.x = rotatedAxisElementText(a,'x'),
          axis.text.y = rotatedAxisElementText(a,'y')) +
    labs(title = sprintf("Rotated %s",a))
})
grid.arrange(grobs=plots)

这会产生以下结果:

示例


1
我没有得到相同的结果,对我来说,使用您的自动方法轴文本从未被很好地调整。然而,使用 rads = (-angle - positions[[position]]) * pi / 180 产生了更好的位置。请注意,在角度之前有额外的减号。无论如何,感谢您提供的代码 :) - asachet
听我说!我想要改变你的函数,使其能够使用任何element_text()参数运行。因此,我在函数中添加了一个名为element_text_params = list()的参数,并将你函数的最后一行替换为element_text_params <- c(element_text_params, list(angle = angle, vjust = vjust, hjust = hjust)),并返回return(do.call(element_text, element_text_params))。这样,我就可以像这样调用你的函数:rotatedAxisElementText(45, "y", element_text_params = list("size" = 10, "face" = "bold") - DoRemy95

14

已过时 - 请查看此答案,以获取更简单的方法


为了在不需要额外依赖的情况下获得易读的x轴标签,您应该使用:

  ... +
  theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) +
  ...

这将把刻度标签逆时针旋转90度,并使它们在其末端垂直对齐(hjust = 1),并水平地与相应的刻度线中心对齐(vjust = 0.5)。

完整示例:

library(ggplot2)
data(diamonds)
diamonds$cut <- paste("Super Dee-Duper",as.character(diamonds$cut))
q <- qplot(cut,carat,data=diamonds,geom="boxplot")
q + theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))


请注意,element_text 的垂直/水平对齐参数 vjust/hjust 是相对于文本的。因此,vjust 负责 水平 对齐。

如果没有 vjust = 0.5,将会看起来像这样:

q + theme(axis.text.x = element_text(angle = 90, hjust = 1))

如果没有hjust=1,它会看起来像这样:

q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

如果出于某些(奇怪的)原因您想将刻度标签顺时针旋转90°(使其可以从左侧读取),您需要使用:q + theme(axis.text.x = element_text(angle = -90, vjust = 0.5, hjust = -1))

所有这些都已在此答案的评论中讨论过,但我经常回到这个问题,所以我想要一个答案,可以直接复制而不必阅读评论。


13

ggpubr包提供了一种默认情况下就做得正确的快捷方式(将文本右对齐,将文本框垂直居中到刻度线):

library(ggplot2)
diamonds$cut <- paste("Super Dee-Duper", as.character(diamonds$cut))
q <- qplot(cut, carat, data = diamonds, geom = "boxplot")
q + ggpubr::rotate_x_text()

此文档由reprex软件包 (v0.2.1)于2018-11-06创建

在GitHub上搜索相关参数名称后发现:https://github.com/search?l=R&q=element_text+angle+90+vjust+org%3Acran&type=Code


0

使用ggstance包是coord_flip()的另一种选择。 它的优点在于,它使得将图形与其他图形类型组合更加容易。而且你可以可能更重要的是,为你的坐标系设置固定的比例尺度。

library(ggplot2)
library(ggstance)

diamonds$cut <- paste("Super Dee-Duper", as.character(diamonds$cut))

ggplot(data=diamonds, aes(carat, cut)) + geom_boxploth()

2020年03月11日使用reprex package (v0.3.0)创建


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接