在*多个*图中具有相同条形宽度*和*相同条形间距的条形图

问题描述 投票:0回答:1

这个问题类似,我想生成几个始终具有相同条形宽度的单独条形图。也就是说,我还希望在每个图中,条形之间的间距是相同的。

我还需要单独保存这些图,并且每个保存的图像大小与条形数量成正比。我不想使用构面或网格(这意味着关于 SO 的类似问题不适用于我)。此外,我需要一个

geom_bar()
解决方案以及
ggsave()

可重现的示例

图书馆

library(tidyverse)
library(ggplot2)

模拟数据(实际上,我有数百个变量,某些因素高达 15 个级别)

df <- structure(list(Animal = structure(c(1L, 2L, 2L, 2L, 1L, 1L, 1L, 
                                          1L, 3L, 3L), levels = c("Cat", "Dog", "Horse"), class = "factor"), 
                     Sex = structure(c(2L, 1L, 1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L), levels = c("Female", 
                                                                                           "Male"), class = "factor")), row.names = c(NA, 10L), class = "data.frame")

生成条形图的函数

# Create counter
counter <- 0

# Function
make_bar_plots <- function(df){ 
  
  # We loop over the columns
  for (col in colnames(df)){ 
    
    # (1) Preparation ##########################################################
    # Store N
    N <- sum(!is.na(df[col]))
    # Store number of levels
    n_levels <- length(unique(df[!is.na(df[col]), col]))[1]
    # Update counter at each iteration
    counter <- counter + 1
    
    # (2) Basic bar plot #######################################################
    # We only plot factors
    if (is.factor(df[[col]])) {
      p <- ggplot(data = df[col] %>% filter(!is.na(df[col])),
                  aes(x=fct_rev(fct_infreq(!!sym(col)))))
      # Compute percents for bars
      p <- p + geom_bar(aes(y = (..count..)/sum(..count..)),
                        width = 0.35*n_levels/3, # We make column width proportional to number of levels!
                        fill = 'black',
                        size = 1.5
      ) 
      
      # (3) Annotations ########################################################
      
      # Add percent as annotation
      p <- p + geom_text(aes(label = scales::percent((..count..)/sum(..count..),
                                                     accuracy = 0.1L),
                             y = ((..count..)/sum(..count..))),
                         stat="count", hjust = -0.1, size=4.2)
      # Add a title
      p <- p + labs(title = paste(col),
                    subtitle = paste0('N = ', format(N, big.mark = ',')
                    ))
      
      # (4) Aesthetics #########################################################
      p <- p + theme_minimal()
      p <- p + theme(axis.title.y = element_blank(),
                     axis.title.x = element_blank(),
                     axis.text.x = element_blank(),
                     axis.text.y = element_text(colour='black', size = 12.5),
                     plot.margin = margin(r=25, l=1, b=0, t=1),
                     plot.title = element_text(size = 16.5),
                     plot.subtitle = element_text(size = 12.5),
                     panel.grid = element_blank()
                     )
      # Flip coordinates
      p <- p + coord_flip(clip = 'off')
      
      # (5) Print and export   #################################################
      print(p)
      # Export
      ggsave(paste(counter, '_', col, '.png'), path = 'plots/', 
             bg = 'white'
      )
    } 
  }
}

输出

make_bar_plots(df)

Plot 1

Plot 2

讨论

我们看到两个图中的条形宽度相同。这是通过函数中包含的参数

width = 0.35*n_levels/3
实现的。

也就是说,与男性和女性(图 2)相比,猫、狗和马(图 1)的条形之间的间距是不同的。

我尝试过的:

  1. ggsave()
    调用中,使用比例调整生成图像的高度(例如,
    height = 2*n_levels/3
    )。也就是说,生成的图具有不同的条形宽度,请参见下图。
  2. 在功能的美观部分,调整宽高比(例如,
    p + theme(aspect.ratio = 1/4)
    )。这也使得各图的条形宽度不同。
  3. 上述的组合,具有相同的不良结果。

使用时图解

height = 2*n_levels/3

Plot 1

Plot 2

我的2个问题:

  1. 我们如何在所有地块上获得相同的条形间距,同时保持所有地块上的条形宽度相同?
  2. 此外,我们如何保存高度会根据条数自动调整的图像?在我的示例中(本文的前两个图),性别图的高度(2 个条)将小于动物图的高度(3 个条)。目前,两者的高度相同。
r ggplot2 tidyverse bar-chart
1个回答
0
投票
通过从

width

 中删除 
geom_bar
 规范并调整绘图输出以反映标题高度(此处为“1”)和每个级别的数量(此处为“0.5”),我得到了不错的结果。调整口味。

ggsave(paste(counter, '_', col, '.png'), path = 'plots/', height = 1 + 0.5*n_levels, bg = 'white' )

enter image description here

enter image description here

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.