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

标签 r plot ggplot2

我目前有一个脚本,它在运行时生成多个相同类型的图形(绘制不同处理对我的数据集中相同类别的影响),这些图形都是在 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() 中指定的大小的影响。 .

看起来我实际上正在寻找的功能是能够通过设置绘图区域的宽度来确定图像的输出宽度,而不是将整个绘图区域的宽度设置为 ggsave("test.png", width = 3)做。 ggplot2 中是否存在这样的功能?

最佳答案

一种(不幸的是不是那么懒惰)的方法是将图例提取为单独的格罗布(图形对象),然后分别布置图和图例。这使您可以更好地控制分配给每个对象的空间量。幸运的是,一些辅助函数使这个过程相对轻松。下面是一个例子:

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

关于r - 如何在多个未分组的图中保持恒定的文本大小和 x 轴比例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34341159/

相关文章:

javascript - 从networkd3中提取节点信息到shiny中的 react 变量

r - 如何将JPEG转换为R中的图像矩阵

r - 带有一些极值的条形图

r - Metafor 森林图 - 改变颜色

R:ggplot2 绘制按工作日分面的每小时数据

r - 用钩子(Hook)在 knitr/rmarkdown 中用 latex 环境包装图形

r - 在 LHS 和 mutate 命令中使用字符串作为变量

python - matplotlib 中未显示绘图窗口

r - ggplot2 中更简单的人口金字塔

r - 趋势线根据 ggplot2 中的轴比例变化