ggplot2:如何动态包装/调整大小/调整x轴标签的大小,以便它们不会重叠 [英] ggplot2: How to dynamically wrap/resize/rescale x axis labels so they won't overlap

查看:207
本文介绍了ggplot2:如何动态包装/调整大小/调整x轴标签的大小,以便它们不会重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一种包装x轴标签的解决方案,以使它们不会重叠.我知道这个问题已经问过几次了,并且有(v0.3.0)创建于2021-01-29


2.当我们使用 ggfittext 时,我们可以看到条形内的标签如何缩小以适合条形

 库(tidyverse)库(ggfittext)#>警告:软件包"ggfittext"是在R版本4.0.3下构建的my_mtcars<-mtcars [15:20,]%&%;%rownames_to_column(汽车")my_mtcars%>%ggplot(aes(x =汽车,y = mpg,填充=汽车))+geom_bar(stat ="identity")+geom_bar_text(aes(label = cars),颜色=蓝色",调整= 1,大小= 7 * ggplot2 ::.pt,最小尺寸= 0,padding.x = grid :: unit(0,"pt"),padding.y = grid :: unit(0,"pt"))#>警告:忽略未知的美学:标签 

由(v0.3.0)创建于2021-01-29


我的问题

我不知道该怎么做,但是我们可以通过某种方式让 ggfittext 为我们完成艰苦的工作来动态地包装/调整大小/缩放x轴标签吗?以我天真的方式看,条形图内的文本已经被正确渲染了,我们可以复制"图样吗?这样以某种方式渲染到轴标签?

解决方案

我们如何将 ggfittext 文本放在y轴下方?我们关闭裁剪,并设置 oob limits 以适合我们的数据.应该调整 axis.text.x 的大小,使其与x轴标题更好地对齐.

 库(tidyverse)#>警告:软件包"tidyr"是在R版本4.0.3下构建的#>警告:软件包"readr"是在R版本4.0.3下构建的#>警告:软件包"dplyr"是在R版本4.0.3下构建的库(ggfittext)#>警告:软件包"ggfittext"是在R版本4.0.3下构建的my_mtcars<-mtcars [15:20,]%&%;%rownames_to_column(汽车")my_mtcars%>%ggplot(aes(x =汽车,y = mpg,填充=汽车))+geom_bar(stat ="identity")+geom_fit_text(aes(label = cars,y = -4),回流= TRUE,高度= 50,show.legend = FALSE)+scale_y_continuous(oob = scales :: oob_keep,限制= c(0,NA))+coord_cartesian(clip ="off")+主题(axis.text.x = element_text(colour ="transparent",大小= 18)) 

reprex软件包(v0.3.0)创建于2021-01-29

从标签中删除标签

 库(tidyverse)库(ggfittext)my_mtcars<-mtcars [15:20,]%&%;%rownames_to_column(汽车")p<-my_mtcars%>%ggplot(aes(x =汽车,y = mpg,填充=汽车))+geom_bar(stat ="identity")+geom_fit_text(aes(label = cars,y = -1),回流= TRUE,高度= 50,show.legend = FALSE)+scale_y_continuous(oob = scales :: oob_keep,限制= c(0,NA))+coord_cartesian(clip ="off")+主题(axis.text.x = element_text(colour ="transparent",大小= 18))grob<-grid :: makeContent(layer_grob(p,2)[[1]])$ children大小<-vapply(grob,function(x){x $ gp $ fontsize},numeric(1))标签<-unname(vapply(grob,function(x){x $ label},character(1)))打印(标签)#>[1]凯迪拉克\弗里特伍德"林肯\大陆"克莱斯勒\帝国"#>[4]菲亚特128"本田思域"丰田\ n花冠" 

reprex软件包(v0.3.0)创建于2021-01-29

I'm trying to achieve a solution for wrapping x axis labels so they won't overlap. I know this question has been asked several times, and that there are some good answers. However, no solution that I've seen answers how to re-wrap the labels as the plot gets resized.

Three different answers at SO make me believe this could be attainable.

  1. This solution wrote a custom-made geom for fitting the bar's label size to fit within the bar's width, dynamically as you resize the plot.

  2. This solution relies on an extension package for ggplot2 called ggtext. The solution allows dynamic word wrapping of the plot's title, as you resize the plot, based on creating a element_textbox().

  3. This solution relies on another extension called ggfittext. It shows how the size of the label inside the bar can vary dynamically to fit the bar's dimensions as you resize the plot. Essentially, it addresses the same problem as solution (1) above, but is much more powerful. In fact, and this is the feature that makes me hopeful, it relies on a general solution geom_fit_text() to fit text inside rectangles, not just geom_bar()s.

Some demo data to work with

1. Just to show the typical output when x axis labels are overlapping

  library(tidyverse)
  
  my_mtcars <-
    mtcars[15:20,] %>% 
    rownames_to_column("cars")
  
  my_mtcars %>%
    ggplot(aes(x = cars, y = mpg, fill = cars)) + 
    geom_bar(stat = "identity")

Created on 2021-01-29 by the reprex package (v0.3.0)


2. When we use ggfittext we can see how labels inside the bars shrink in size to fit the bar

  library(tidyverse)
  library(ggfittext)
#> Warning: package 'ggfittext' was built under R version 4.0.3
  
  my_mtcars <-
    mtcars[15:20,] %>% 
    rownames_to_column("cars")
  
  my_mtcars %>%
    ggplot(aes(x = cars, y = mpg, fill = cars)) + 
    geom_bar(stat = "identity") +
    geom_bar_text(aes(label = cars), 
      color = "blue", 
      vjust = 1, 
      size = 7 * ggplot2::.pt, 
      min.size = 0,
      padding.x = grid::unit(0, "pt"),
      padding.y = grid::unit(0, "pt"))
#> Warning: Ignoring unknown aesthetics: label

Created on 2021-01-29 by the reprex package (v0.3.0)


3. ggtext has the reflow argument that promotes text wrapping

  library(tidyverse)
  library(ggfittext)
#> Warning: package 'ggfittext' was built under R version 4.0.3
  
  my_mtcars <-
    mtcars[15:20,] %>% 
    rownames_to_column("cars")
  
  my_mtcars %>%
    ggplot(aes(x = cars, y = mpg, fill = cars)) + 
    geom_bar(stat = "identity") +
    geom_bar_text(aes(label = cars), 
      color = "blue", 
      vjust = 1, 
      size = 7 * ggplot2::.pt, 
      min.size = 0,
      padding.x = grid::unit(0, "pt"),
      padding.y = grid::unit(0, "pt"),
      reflow = TRUE ## <--------------- added this
      )
#> Warning: Ignoring unknown aesthetics: label

Created on 2021-01-29 by the reprex package (v0.3.0)


My question

I don't know how to do it, but could we get x axis labels wrapped/resized/rescaled dynamically, by somehow letting ggfittext do the hard work for us? In the naïve way I see this, the text within the bars is already rendered the right way, can we just "copy" this rendering somehow to the axis labels?

解决方案

How about we just place the ggfittext text below the y-axis? We turn off clipping and set the oob and limits to suit our data. Should probably tweak the axis.text.x size to align better with the x-axis title.

library(tidyverse)
#> Warning: package 'tidyr' was built under R version 4.0.3
#> Warning: package 'readr' was built under R version 4.0.3
#> Warning: package 'dplyr' was built under R version 4.0.3
library(ggfittext)
#> Warning: package 'ggfittext' was built under R version 4.0.3

my_mtcars <-
  mtcars[15:20,] %>% 
  rownames_to_column("cars")

my_mtcars %>%
  ggplot(aes(x = cars, y = mpg, fill = cars)) + 
  geom_bar(stat = "identity") +
  geom_fit_text(aes(label = cars, y = -4),
                reflow = TRUE, height = 50,
                show.legend = FALSE) +
  scale_y_continuous(oob = scales::oob_keep,
                     limits = c(0, NA)) +
  coord_cartesian(clip = "off") +
  theme(axis.text.x = element_text(colour = "transparent", size = 18))

Created on 2021-01-29 by the reprex package (v0.3.0)

EDIT: Getting the labels out of the grob

library(tidyverse)
library(ggfittext)

my_mtcars <-
  mtcars[15:20,] %>% 
  rownames_to_column("cars")

p <- my_mtcars %>%
  ggplot(aes(x = cars, y = mpg, fill = cars)) + 
  geom_bar(stat = "identity") +
  geom_fit_text(aes(label = cars, y = -1),
                reflow = TRUE, height = 50,
                show.legend = FALSE) +
  scale_y_continuous(oob = scales::oob_keep,
                     limits = c(0, NA)) +
  coord_cartesian(clip = "off") +
  theme(axis.text.x = element_text(colour = "transparent", size = 18))

grob <- grid::makeContent(layer_grob(p, 2)[[1]])$children

sizes <- vapply(grob, function(x){x$gp$fontsize}, numeric(1))
labels <- unname(vapply(grob, function(x){x$label}, character(1)))
print(labels)
#> [1] "Cadillac\nFleetwood"  "Lincoln\nContinental" "Chrysler\nImperial"  
#> [4] "Fiat 128"             "Honda Civic"          "Toyota\nCorolla"

Created on 2021-01-29 by the reprex package (v0.3.0)

这篇关于ggplot2:如何动态包装/调整大小/调整x轴标签的大小,以便它们不会重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆