首页 文章

如何在多个未分组的图上保持恒定的文本大小和x轴比例

提问于
浏览
4

我目前有一个脚本,可以在运行时生成相同类型的多个图形(绘制不同处理对我的数据集中相同类别的影响),这些都是在x轴上具有相同值的躲避条形图 . 一个例子是:

d <- data.frame(x = runif(1000), y = runif(1000)^2, very_long_label_name = runif(1000)^3)
d <- round(d, 1)
d <- melt(d)
qplot(data = d[d$variable != "very_long_label_name",], factor(value), position = "dodge", 
      geom = "histogram", fill = variable)
ggsave("test1.png", height = 3.5, width = 4.5)
qplot(data = d[d$variable != "y",], factor(value), position = "dodge",
      geom = "histogram", fill = variable)
ggsave("test2.png", height = 3.5, width = 4.5)

由于我的数据是躲闪条形图,我在侧面有一个酒吧颜色的传奇 . 但由于每个图形都比较了不同的处理方式,因此图例上的标签长度不同,因此最终会出现不同宽高比和文字大小的数字 . 有没有办法让我控制文本的大小和多个数字的x轴宽度?

我试过看How to control ggplot's plotting area proportions instead of fitting them to devices in R?coord_fixed() 似乎被 ggsave() 忽略了 . How can I make consistent-width plots in ggplot (with legends)?是一个非常类似的问题,但答案似乎都假设我将这些数字放在一起而不是将它们分散在纸上 . 使用 theme_set() 至少对于字体大小问题似乎很有希望,除了文本的最终大小然后受 ggsave() 中指定的大小的影响 .

通过设置绘图区域的宽度,而不是整个绘图区域的宽度,看起来像是'm actually looking for would be the ability to determine an image'的输出宽度,如 ggsave("test.png", width = 3) . ggplot2中是否存在这样的功能?

2 回答

  • 0

    一个(不幸的是不是那么懒惰)的方法是将图例作为单独的grobs(图形对象)提取出来,然后分别绘制图表和图例 . 这使您可以更好地控制为每个对象分配多少空间 . 幸运的是,一些辅助函数使得该过程相对无痛 . 这是一个例子:

    library(gridExtra) 
    
    p1 = qplot(data = d[d$variable != "very_long_label_name",], factor(value), 
               position = "dodge", geom = "histogram", fill = variable)
    
    p2 = qplot(data = d[d$variable != "y",], factor(value), position = "dodge",
          geom = "histogram", fill = variable)
    

    我们需要一些辅助函数,一个用于提取图例,另一个用于证明图例格式,因此它们排成一行:

    # Function to extract legend as a separate grob
    # Source: http://stackoverflow.com/a/12539820/496488
    get_leg = function(a.gplot){
      tmp <- ggplot_gtable(ggplot_build(a.gplot))
      leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
      legend <- tmp$grobs[[leg]]
      legend
    }
    
    # Function to left justify the legends so they line up
    # Source: http://stackoverflow.com/a/25456672/496488
    justify <- function(x, hjust="center", vjust="center", draw=TRUE){
      w <- sum(x$widths)
      h <- sum(x$heights)
      xj <- switch(hjust,
                   center = 0.5,
                   left = 0.5*w,
                   right=unit(1,"npc") - 0.5*w)
      yj <- switch(vjust,
                   center = 0.5,
                   bottom = 0.5*h,
                   top=unit(1,"npc") - 0.5*h)
      x$vp <- viewport(x=xj, y=yj)
      if(draw) grid.draw(x)
      return(x)
    }
    

    现在提取传说并列出情节:

    # Extract each legend
    leg1 = get_leg(p1)
    leg2 = get_leg(p2)
    
    # Allocate proportions of layout width to plot and legend
    w = c(0.6,0.4)
    
    # Lay out plot and legend separately
    png("test1.png", height = 3, width = 6, units="in", res=100)
    grid.arrange(p1 + theme(legend.position="none"), 
                 justify(leg1,"left","center"),
                 widths=w, ncol=2)
    dev.off()
    
    png("test2.png", height = 3, width = 6, units="in", res=100)
    grid.arrange(p2 + theme(legend.position="none"), 
                 justify(leg2,"left","center"),
                 widths=w, ncol=2)
    dev.off()
    

    enter image description here

    enter image description here

    如果出现实际数据,还有一个皱纹:如果图形的y值发生变化,由于更多宽度分配给y轴标签,最终可能会使绘图区域不垂直对齐(当y值有更多字符时,减去绘图区域 . 然后,您还需要均衡绘图区域的宽度,以便绘图区域也垂直排列 . 这是一个例子:

    # New plot with a different data set
    p3 = ggplot(iris, aes(Sepal.Length, Sepal.Width*1e6, colour=Species)) +
            geom_point()
    
    leg3 = get_leg(p3)
    
    # Justify widths
    # Source: http://stackoverflow.com/a/13295880/496488
    gA <- ggplotGrob(p1 + theme(legend.position="none"))
    gB <- ggplotGrob(p3 + theme(legend.position="none"))
    maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
    gA$widths[2:5] <- as.list(maxWidth)
    gB$widths[2:5] <- as.list(maxWidth)
    
    png("test1a.png", height = 3, width = 6, units="in", res=100)
    grid.arrange(gA, justify(leg1,"left","center"),
                 widths=w, ncol=2)
    dev.off()
    
    png("test3.png", height = 3, width = 6, units="in", res=100)
    grid.arrange(gB, justify(leg3,"left","center"),
    widths=w, ncol=2)
    dev.off()
    

    现在这里是原始的p1,接着是p1和p3的宽度调整版本:

    enter image description here

    enter image description here

    enter image description here

  • 2

    懒惰的解决方案,但可能只是为了您的目的:将图例放在底部

    qplot(data = d[d$variable != "very_long_label_name",], factor(value), 
          position = "dodge", geom = "histogram", fill = variable) +
      theme(legend.position = 'bottom')
    
    qplot(data = d[d$variable != "y",], factor(value),
          position = "dodge", geom = "histogram", fill = variable)  +
      theme(legend.position = 'bottom')
    

    enter image description here

    enter image description here

相关问题