【问题标题】:Rotating and spacing axis labels in ggplot2ggplot2中的旋转和间距轴标签
【发布时间】:2022-01-11 18:22:58
【问题描述】:

我有一个图,其中 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))

【问题讨论】:

  • 由于 ggplot 3.3.0 现已推出,IMO 接受的答案应更改为 jan-glxs one

标签: r ggplot2 label


【解决方案1】:

使用coord_flip()

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

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


添加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()


R for Data Science 的第 3.9 章中,Wickham 和 Grolemund 谈到了这个确切的问题:

coord_flip() 切换 x 和 y 轴。如果您想要水平箱线图,这很有用(例如)。它对于长标签也很有用:很难让它们在 x 轴上不重叠。

【讨论】:

    【解决方案2】:

    已过时 - 请参阅 this answer 了解更简单的方法


    要在没有额外依赖的情况下获得可读的 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))
    


    请注意,vjust/hjust 的垂直/水平对齐参数 element_text 与文本相关。因此,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))

    所有这些已经在this answer 的 cmets 中讨论过,但我经常回到这个问题,我想要一个答案,我可以从中复制而不阅读 cmets。

    【讨论】:

      【解决方案3】:

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

      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
      

      来自the documentation of the angle argument

      与在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
      

      【讨论】:

      • 虽然我喜欢这里的躲避解决方案,但值得注意的是guide_axis(angle=90) 选择了正确的 vjust 和 hjust 值,这解决了 OP 中的问题。
      • @eipi10 谢谢,我不知道,现在将其添加到答案中!
      【解决方案4】:

      将最后一行改为

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

      默认情况下,轴在文本的中心对齐,即使在旋转时也是如此。当您旋转 +/- 90 度时,您通常希望它在边缘对齐:

      上图来自this blog post

      【讨论】:

      • 在最新版本的 ggplot2 中,命令为:q + theme(axis.text.x=element_text(angle = -90, hjust = 0))
      • 对于那些不符合此处描述的行为的人,请尝试theme(axis.text.x=element_text(angle = 90, vjust = 0.5))。从 ggplot2 0.9.3.1 开始,这似乎是解决方案。
      • 实际上,我必须结合上述两种解决方案才能获得正确对齐的标签:q + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
      • @jupp0r 是正确的。 theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) 是当前工作的那个。
      • 如果您想要 45° 旋转标签(更易于阅读)theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1)) 会得到很好的结果
      【解决方案5】:

      coord_flip() 的替代方法是使用 ggstance 包。 优点是它可以更轻松地将图形与其他图形类型结合起来,而且您可以,也许更重要的是,为您的坐标系设置固定比例

      library(ggplot2)
      library(ggstance)
      
      diamonds$cut <- paste("Super Dee-Duper", as.character(diamonds$cut))
      
      ggplot(data=diamonds, aes(carat, cut)) + geom_boxploth()
      

      reprex package (v0.3.0) 于 2020-03-11 创建

      【讨论】:

        【解决方案6】:

        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 package (v0.2.1) 于 2018 年 11 月 6 日创建

        通过 GitHub 搜索找到相关参数名称:https://github.com/search?l=R&q=element_text+angle+90+vjust+org%3Acran&type=Code

        【讨论】:

          【解决方案7】:

          要使刻度标签上的文本完全可见并且与 y 轴标签的读取方向相同,请将最后一行更改为

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

          【讨论】:

            【解决方案8】:

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

            基本上,您需要使用三角函数确定相对位置,方法是构建一个返回element_text 对象、给定角度(即度数)和定位(即x、y、顶部或右侧之一)信息的函数。

            #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)
            }
            

            坦率地说,在我看来,我认为应该在ggplot2 中为hjustvjust 参数提供一个“自动”选项,无论如何,在指定角度时,让我们演示一下上面的工作原理。

            #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)
            

            这会产生以下内容:

            【讨论】:

            • 我没有得到相同的结果,对我来说,轴文本从来没有使用你的 auto 方法很好地调整过。但是,使用rads = (-angle - positions[[ position ]])*pi/180 会产生更好的展示位置。注意角度前的附加减号。无论如何感谢您的代码:)
            • 得到想法!我想调整您的函数,使其能够使用element_text() 的任何参数运行它。所以我在函数中添加了一个名为element_text_params = list() 的参数,并将函数中的最后一行替换为element_text_params &lt;- 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")
            猜你喜欢
            • 2012-04-21
            • 2017-09-22
            • 1970-01-01
            • 2017-09-23
            • 1970-01-01
            • 1970-01-01
            • 2013-02-04
            • 1970-01-01
            相关资源
            最近更新 更多