ggplot2瓷砖用不同高度的水平面板绘制

时间:2014-02-13 17:21:21

标签: r ggplot2 facet-wrap

这基本上是同一个问题this one,但有一个重要的区别:我想要一个带有水平面板的基于ggplot2的平铺图,并且所有的瓷砖高度相等。另一个问题是垂直面板。

以下是一些示例代码,基于另一个问题中的代码:

d = data.frame(sites=rep(paste("S", 1:31),each=12),
               month=factor(rep(1:12,31)),
               value=runif(31*12),
               panel=c(rep("Group 1",16*12), rep("Group 2", 12*12),
                       rep("Group 3", 3*12)))

使用

绘制图片
ggplot(d, aes(x=month, y=sites, fill=value)) + 
  geom_tile(colour="white") + facet_wrap(~panel, nrow=1)

结果为enter image description here

基本上,我希望每块蓝色瓷砖向上移动,以便它们上方没有空间。我可以使用

实现这一目标
ggplot(d, aes(x=month, y=sites, fill=value, colour="white")) + 
  geom_tile(colour="white") + facet_wrap(~panel, scales="free_y", nrow=1)

但这导致高度不等的瓷砖:

enter image description here

The other question有一个很好的垂直面板解决方案,但将此应用于上述代码无效。水平面板有类似的解决方案吗?

2 个答案:

答案 0 :(得分:4)

以下是使用gridExtra并设置级别的黑客攻击:

d.splt <- split(d, d$panel)
max.unique <- max(sapply(d.splt, function(x) length(unique(x$sites))))
d.gg <- lapply(d.splt, function(d.sub){
  lvls <- unique(as.character(d.sub$sites))
  length(lvls) <- max.unique
  lvls <- replace(lvls, is.na(lvls), "")
  d.sub$sites <- factor(as.character(d.sub$sites), levels=lvls)

  ggplot(d.sub, aes(x=month, y=sites, fill=value, colour="white")) + 
    geom_tile(colour="white", stat="identity") +
    scale_y_discrete(drop=F) + scale_fill_continuous(guide=F)
} )
library(gridExtra)
do.call(grid.arrange, c(d.gg, list(nrow=1)))

enter image description here

这会抛出一些警告,但你可以忽略它们。此外,您还需要添加标题和图例(您可以使用逻辑,以便最后一个生成图例)。

这个问题的主要问题是色标将独立地适合每个图形,但是你可以强制它被修复。

答案 1 :(得分:0)

我会接受@ BrodieG的解决方案,因为这是我的问题的最通用的解决方案,但我会添加我自己的,对于特殊情况,实际的行/站点名称无关紧要,只有(内-panel)tile行的顺序。在这里,我们可以使用hack,我们将所有子组中的级别名称更改为具有最大行数的组中使用的级别名称。示例数据和原始图:

# Example data
set.seed(7)
d = data.frame(sites=rep(paste("S", 1:31),each=12),
               month=factor(rep(1:12,31)),
               value=runif(31*12),
               panel=c(rep("Group 1",16*12),
                       rep("Group 2", 12*12),
                       rep("Group 3", 3*12)))

# Reorder rows / site names (just to show that the code works properly)
d$sites = reorder(d$sites, d$value, mean)

# Original plot
library(ggplot2)
ggplot(d, aes(x=month, y=sites, fill=value)) + 
  geom_tile(colour="white") + facet_wrap(~panel, nrow=1)

enter image description here

现在我们只需要更改每个子组的站点名称:

# Fetch the name of the group with the most rows
library(plyr)
d.stat = ddply(d, .(panel), summarise, nrows=length(unique(sites)))
maxpanel = with(d.stat, panel[which.max(nrows)])

# Fetch the levels / rownames of the group with the most rows
levels.maxpanel = levels(droplevels(subset(d, panel==maxpanel))$sites)

# Substitute the levels / row names of the
# biggest group for each subgroup
subs.levels = function(d.sub) {
  levels.subpanel = rev(levels(droplevels(d.sub$sites)))
  d.sub$sites[] = rev(levels.maxpanel)[match(d.sub$sites, levels.subpanel)]
  d.sub
}
d.recoded = ddply(d, .(panel), subs.levels)

# New plot
ggplot(d.recoded, aes(x=month, y=sites, fill=value)) + 
  geom_tile(colour="white") + facet_wrap(~panel, nrow=1) +
  theme(axis.text.y=element_blank()) 

enter image description here