2012-07-23 66 views
9

此问题的动机是进一步探索此question。如果每个方面的条纹数量存在较大差异,那么接受解决方案的问题就会变得更加明显。看看这些数据并将所得的情节使用的解决方案:ggplot2 + gridExtra:如何确保geom_bar在不同尺寸的绘图区域中产生完全相同的横条宽度

# create slightly contrived data to better highlight width problems 
data <- data.frame(ID=factor(c(rep(1,9), rep(2,6), rep(3,6), rep(4,3), rep(5,3))), 
        TYPE=factor(rep(1:3,length(ID)/3)), 
        TIME=factor(c(1,1,1,2,2,2,3,3,3,1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,1,1,1)), 
        VAL=runif(27)) 

# implement previously suggested solution 
base.width <- 0.9 
data$w <- base.width 
# facet two has 3 bars compared to facet one's 5 bars 
data$w[data$TIME==2] <- base.width * 3/5 
# facet 3 has 1 bar compared to facet one's 5 bars 
data$w[data$TIME==3] <- base.width * 1/5 
ggplot(data, aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~TIME, ncol=1, scale="free") + 
    geom_bar(position="stack", aes(width = w),stat = "identity") + 
    coord_flip() 

widths all the same but spacing is bad

你会注意到的宽度看起来完全正确的,但在棱面3的空格是非常明显的。有没有简单的方法来解决这个我已经看到的ggplot2(facet_wrap没有space选项)。

下一步是尝试解决这个使用gridExtra:

# create each of the three plots, don't worry about legend for now 
p1 <- ggplot(data[data$TIME==1,], aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~ TIME, ncol=1) + 
    geom_bar(position="stack", show_guide=FALSE) + 
    coord_flip() 
p2 <- ggplot(data[data$TIME==2,], aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~ TIME, ncol=1) + 
    geom_bar(position="stack", show_guide=FALSE) + 
    coord_flip() 
p3 <- ggplot(data[data$TIME==3,], aes(x=ID, y=VAL, fill=TYPE)) + 
    facet_wrap(~ TIME, ncol=1) + 
    geom_bar(position="stack", show_guide=FALSE) + 
    coord_flip() 

# use similar arithmetic to try and get layout correct 
require(gridExtra) 
heights <- c(5, 3, 1)/sum(5, 3, 1) 
print(arrangeGrob(p1 ,p2, p3, ncol=1, 
      heights=heights)) 

widths wrong

你会发现我用同样的算术先前建议基于关每小条的数量,但在这情况下,它结束了可怕的错误。这似乎是因为在数学中我需要考虑额外的“恒定高度”元素。 (我相信)的另一个复杂因素是最终输出(以及宽度是否匹配)还将取决于输出最终grob的位置的宽度和高度,无论它在R/RStudio中环境或PNG文件。

我该如何做到这一点?

+1

用'ggplot_build'你可以在你的第一个解决方案直接修改每个面板的高度。 kohske在此处发布了示例 – baptiste 2012-07-23 04:29:21

+0

@baptiste谢谢,请稍后再看看并更新问题 – 2012-07-23 04:30:27

回答

2

更改gtable没有帮助,不幸的是,线条的宽度是相对单位,

g = ggplot_gtable(ggplot_build(p)) 
panels = which(sapply(g$heights, attr, "unit") == "null") 
g$heights[[panels[1]]] <- unit(5, "null") 
g$heights[[panels[2]]] <- unit(3, "null") 
g$heights[[panels[3]]] <- unit(1, "null") 
grid.draw(g) 

enter image description here

+0

那么回到通过gridExtra安排各个方面了吗? – 2012-07-23 11:26:11

5

像这样的事情似乎工作,但它没有 - 不完全。它具有工作的外观,因为ID因子的级别是连续的。别的,scale = "free"失败。但有可能进一步发展。该方法使用facet_grid,因此可以使用space = "free"。该方法使用geom_rect将不同颜色的矩形叠放在一起。它需要计算累积和,以便可以定位每个矩形的右侧边缘。

data <- data.frame(ID=factor(c(rep(1,9), rep(2,6), rep(3,6), rep(4,3), rep(5,3))), 
        TYPE=factor(rep(1:3,3)), 
        TIME=factor(c(1,1,1,2,2,2,3,3,3,1,1,1,2,2,2,1,1,1,2,2,2,1,1,1,1,1,1)), 
        VAL=runif(27)) 

library(ggplot2) 
library(plyr) 

# Get the cumulative sums 
data = ddply(data, .(ID, TIME), mutate, CUMSUMVAL = cumsum(VAL)) 

ggplot(data, aes(x=VAL, y = as.numeric(ID), fill=TYPE)) + 
    geom_rect(data = subset(data, TYPE == 3), aes(xmin = 0, xmax = CUMSUMVAL, ymin = as.numeric(ID)-.2, ymax = as.numeric(ID)+.2)) + 
    geom_rect(data = subset(data, TYPE == 2), aes(xmin = 0, xmax = CUMSUMVAL, ymin = as.numeric(ID)-.2, ymax = as.numeric(ID)+.2)) + 
    geom_rect(data = subset(data, TYPE == 1), aes(xmin = 0, xmax = CUMSUMVAL, ymin = as.numeric(ID)-.2, ymax = as.numeric(ID)+.2)) + 
    facet_grid(TIME~., space = "free", scale="free") + 
    scale_y_continuous(breaks = c(1:5), expand = c(0, 0.2)) 

enter image description here

编辑:还是真的粗线工作好一点(我认为)

ggplot(data, aes(x=VAL, y = ID, colour=TYPE)) + 
     geom_segment(data = subset(data, TYPE == 3), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
     geom_segment(data = subset(data, TYPE == 2), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
     geom_segment(data = subset(data, TYPE == 1), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
     facet_grid(TIME~., space = "free", scale="free") 

enter image description here

其他编辑以从earleir数据发布,并修改它一点。
更新opts已弃用;改为使用theme

df <- structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 
5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L, 6L, 7L, 7L, 7L), .Label = c("a", 
"b", "c", "d", "e", "f", "g"), class = "factor"), TYPE = structure(c(1L, 
2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 
1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 
5L, 6L, 1L, 2L, 3L), .Label = c("1", "2", "3", "4", "5", "6", 
"7", "8"), class = "factor"), TIME = structure(c(2L, 2L, 2L, 
2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 
1L, 1L, 1L), .Label = c("One", "Five", "Fifteen"), class = "factor"), VAL = c(0.937377670081332, 
0.522220720537007, 0.278690102742985, 0.967633064137772, 0.116124767344445, 
0.0544306698720902, 0.470229141646996, 0.62017166428268, 0.195459847105667, 
0.732876230962574, 0.996336271753535, 0.983087373664603, 0.666449476964772, 
0.291554537601769, 0.167933790013194, 0.860138458199799, 0.172361251665279, 
0.833266809117049, 0.620465772924945, 0.786503327777609, 0.761877260869369, 
0.425386636285111, 0.612077651312575, 0.178726130630821, 0.528709076810628, 
0.492527724476531, 0.472576208412647, 0.0702785139437765, 0.696220921119675, 
0.230852259788662, 0.359884874196723, 0.518227979075164, 0.259466265095398, 
0.149970305617899, 0.00682218233123422, 0.463400925742462, 0.924704828299582, 
0.229068386601284)), .Names = c("ID", "TYPE", "TIME", "VAL"), row.names = c(NA, 
-38L), class = "data.frame") 

library(ggplot2) 
library(plyr) 

data = ddply(df, .(ID, TIME), mutate, CUMSUMVAL = cumsum(VAL)) 

ggplot(data, aes(x=VAL, y = ID, colour=TYPE)) + 
      geom_segment(data = subset(data, TYPE == 6), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 5), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 4), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 3), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 2), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      geom_segment(data = subset(data, TYPE == 1), aes(x = 0, xend = CUMSUMVAL, y = ID, yend = ID), size = 10) + 
      facet_grid(TIME~., space = "free", scale="free") + 
      theme(strip.text.y = element_text(angle = 0)) 

enter image description here

+0

聪明!这将工作,除了facet标签在右侧以及在我的实际数据中,我的ID列实际上是一个因素,有时候是特定的ID,TIME组合将会缺少一个类型。现在进行测试,以了解它与我的实际数据的一致性。 – 2012-07-23 15:10:48

相关问题