首页 > 解决方案 > 自动调整大小和固定宽度的条形图

问题描述

我遇到了麻烦,我不知道该怎么解释,所以提前抱歉。

我有一个脚本,因为它非常大,所以我不会放在这里,所以让我们直接进入问题。

由于脚本会生成一个直方图徽标,因此我将尝试通过示例来模拟问题。

我正在使用一个函数根据条的数量分割直方图,最后,它会生成一个带有各种 grobs 的图,每个 grobs 都包含一段直方图。

myranges <- function(start, end, step){
  starts <- seq(start, end, step+1)
  ends <- pmin(starts + step, end)
  data.frame(a = starts, b = ends)
}

d <- data.frame(a = letters[1:10] , b = seq(1, 20, by =2 ))


num_bar_per_hist <- 2

p_list <- apply(
  myranges(1, nrow(d), num_bar_per_hist - 1),
  1,
  function(x){
    #as.matrix(d[x[1]:x[2]],)
    ggplot(d[x[1]:x[2] , ], aes(x=a, y=b)) + 
      geom_bar(stat = "identity") +
      ylim(0,22) +
      theme_classic()
  }
)
do.call(gridExtra::grid.arrange, c(p_list, ncol=2))

上面是生成情节的脚本片段。
我更改 varnum_bar_per_hist以拆分直方图。在这个例子中,我得到了这个:

在此处输入图像描述

如果我将值更改num_bar_per_hist为 5,我得到:

在此处输入图像描述

这两个示例表明每个图的宽度保持不变,条形的宽度也是如此。
但是,如果我将 更改num_bar_per_hist为 3 我得到:

在此处输入图像描述

我想要的是保持条形的宽度相同。这意味着,条形j应该对齐并且与d正上方的条的宽度相同。

另外,如果可能的话,我不想改变脚本的结构(太多),或者简单/小的改变。

我提前表示感谢。谢谢

编辑:

使用cowplot我可以解决部分问题。(与第三个图相同的参数)

num_bar_per_hist <- 3

p_list <- apply(
  myranges(1, nrow(d), num_bar_per_hist - 1),
  1,
  function(x){
    ggdraw() +
      draw_plot(
        ggplot(d[x[1]:x[2] , ], aes(x=a, y=b)) + 
          geom_bar(stat = "identity") +
          ylim(0, 22),
        width = (x[2] - x[1] + 1) / num_bar_per_hist
      )
  }
)
do.call(gridExtra::grid.arrange, c(p_list, ncol=2))

这样我得到:

在此处输入图像描述

这样我就接近解决方案了。仍然没有与其他人相同的j宽度,但比第三个地块好太多了。
我仍然需要一些技巧或“魔术数字”来提高条形的宽度。由于这种策略领先,最后一个 grob 变得比其他人更薄。而且我只想保持所有条的宽度相同,而与每个图所具有的条数的差异无关。

标签: rggplot2widthautosizegridextra

解决方案


您可以找出中断的数量,然后从那里修改每个图,以确保它们都有尽可能多的中断,方法是在 x 刻度上添加虚拟的,

how_many <- function(p){
  gb <- ggplot_build(p)
  length(gb$layout$panel_params[[1]][['x.major']])
}

raxe <- function(p, n){

  gb <- ggplot_build(p)
  x_params <- gb$layout$panel_params[[1]]
  ni <- length(x_params[['x.major']])
  labels <- x_params[['x.labels']]
  if(ni < n){
    dummy <- c(labels, paste0("__",letters[seq_len(n-ni)]))
    print(dummy)
    phantom <- c(labels, rep('', n-ni))
    return(p + scale_x_discrete(lim=dummy, labels=phantom))
  }
p
}

n_breaks <- sapply(p_list, how_many)
p_list <- lapply(p_list, raxe, max(n_breaks))

egg::ggarrange(plots = p_list, ncol=2)

推荐阅读