2014-02-13 3 views
1

Это в основном тот же вопрос this one, но с одним важным отличием: я хочу ggplot2 на основе плитки участок с горизонтальных панелей, и где все плитки имеют одинаковую высоту , Другой вопрос касался вертикальных панелей.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))) 

Plotting это с помощью

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 имел хорошее решение для вертикальных панелей, но их применение для приведенной выше коды не имеет никакого эффекта. Есть ли аналогичное решение для горизонтальных панелей?

ответ

3

Вот хак с помощью 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

Это выбросит некоторые предупреждения, но вы можете их игнорировать. Кроме того, вам нужно будет добавить заголовки, а также легенду (вы можете испортить логику, чтобы последняя создавала легенду).

Основная проблема заключается в том, что цветовая гамма будет пригодна для каждого графика независимо, но там вы можете заставить это фиксироваться.

+0

Спасибо за хорошее решение. И достаточно легко перейти на перемещение блоков вверх, а не снизу. Однако одна вещь, которую я бы изменила, - это 'lvls <- unique (as.character (d.sub $ sites))' to 'lvls <- levels (droplevels (d.sub $ sites))', чтобы сохранить порядок строки (это не имеет значения для моих примерных данных, так как строки уже были помечены/упорядочены численно), но для других данных это будет иметь значение. –

0

Я приму решение @ BrodieG, поскольку это наиболее общее решение для моего вопроса, но я добавлю свое собственное, для специального случая, когда фактические имена строк/сайтов не имеют значения, только (внутри панели) порядок рядов плитки. Здесь мы можем использовать хак, где мы меняем имена уровней во всех подгруппах на те, которые используются в группе с наибольшим количеством строк. Пример данных и оригинальный сюжет:

# 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

Смежные вопросы