2016-03-02 2 views
1

У меня есть данные, собранные на трех сайтах, где в каждом из этих данных было собрано несколько раз для нескольких предметов.ggplot панель гистограмм с гистограммами в качестве подзаголовков

Вот как данные выглядят так:

set.seed(1) 
df <- data.frame(site = c(rep("AA",1000),rep("BB",500),rep("CC",750)), 
       y = c(rnorm(1000,1,2),runif(500,1,3),rgamma(750,shape=1))) 

#add subjects - using a function that randomly generates 
#a number of subjects that adds up to their total at that site 

site_a_subjects <- diff(c(0, sort(20*sample(19)), 1000)) 
site_b_subjects <- diff(c(0, sort(30*sample(9)), 500)) 
site_c_subjects <- diff(c(0, sort(40*sample(4)), 750)) 

#add these subjects 
df$site_subjects <- c(unlist(sapply(1:20, function(x) rep(letters[x], site_a_subjects[x]))), 
        unlist(sapply(1:10, function(x) rep(letters[x], site_b_subjects[x]))), 
        unlist(sapply(1:5, function(x) rep(letters[x], site_c_subjects[x])))) 

Я хочу, чтобы построить гистограмму y на каждом сайте. Эта ggplot2 простая линия, которая легко достигается:

ggplot(df, aes(x=y)) + geom_histogram(colour="black", fill="white") + facet_grid(. ~ site) 

Однако я дополнительно хочу построить на каждом сайте гистограмме, а сюжетные, который представляет собой гистограмму подсчетов числа каждого объекта наблюдения на этом сайте. Что-то вроде добавления:

hist(table(df$site_subjects[which(df$site == "AA")])) 
hist(table(df$site_subjects[which(df$site == "BB")])) 
hist(table(df$site_subjects[which(df$site == "CC")])) 

к трем гистограмм сайта, соответственно.

Любая идея, как это можно сделать?

Интересно, можно ли настроить annotation_custom, чтобы достичь этого?

Этот код будет работать, но только если:

ggplotGrob(ggplot(df, aes(x=site_subjects)) + geom_bar() + theme_bw(base_size=9)) 

команда может согласиться с list из ggplot объектов или что-то подобное.

вот «почти; Решение: Первая цифра, что максимальная высота штриха среди все фаски гистограмм

ymax <- max(sapply(unique(df$site), function(x) max(hist(df$y[which(df$site == x)],plot=FALSE)$counts))) 

Тогда:

main.plot <- ggplot(df, aes(x=y)) + geom_histogram(colour="black", fill="gray") + facet_grid(~site) + scale_y_continuous(limits=c(0,1.2*ymax)) 
main.plot.info <- ggplot_build(main.plot) 
xmin <- min(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)]) 
xmax <- max(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)]) 
main.plot <- main.plot + annotation_custom(grob = grid::roundrectGrob(),xmin = xmin, xmax = xmax, ymin=ymax, ymax=1.2*ymax) 
sub.plot <- ggplotGrob(ggplot(df, aes(x=site_subjects)) + geom_bar() + theme_bw(base_size=9)) 
combined.plot <- main.plot + annotation_custom(grob = sub.plot, xmin = xmin, xmax = xmax, ymin=ymax, ymax=1.2*ymax) 

И результат: enter image description here

ответ

2

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

library(grid) 

# Function to draw the inset plots 
    pp = function(var) { 
    grid.draw(
     ggplotGrob(
     ggplot(df[df$site==var,], aes(site_subjects)) + 
      geom_bar() + 
      theme_bw(base_size=9) 
    ) 
    ) 
    } 

# Function to place the viewports on the main graph 
my_vp = function(x) { 
    viewport(x=x, y=.8, width=0.25, height=0.2) 
} 

# Main plot 
ggplot(df, aes(x=y)) + geom_histogram(colour="black", fill="white") + 
    facet_grid(. ~ site) + 
    scale_y_continuous(limits=c(0,400)) 

# Draw each inset plot in a separate viewport 
vp = my_vp(0.22) 
pushViewport(vp) 
pp("AA") 
popViewport() 

vp = my_vp(0.52) 
pushViewport(vp) 
pp("BB") 
popViewport() 

vp = my_vp(0.84) 
pushViewport(vp) 
pp("CC") 

enter image description here

+0

Nice !!! Есть ли способ предопределить местоположения х фассов основного сюжета, чтобы они могли быть переданы в my_vp вместо жесткого кодирования значений? – user1701545

+0

А также, как бы мне изменить этот код, чтобы я мог нарисовать фигуру в файл? – user1701545

+0

Для вашего второго вопроса, прямо перед тем, как вы начнете основной сюжет, сделайте 'tiff (« myplot.tiff », 1000, 800)' (или любое другое имя и разрешение файла), после добавления всех вложенных графиков выполните 'dev.off() '. – eipi10

0

Вот что-то разумное:

ymax <- max(sapply(unique(df$site), function(x) max(hist(df$y[which(df$site == x)],plot=FALSE)$counts))) 
sites <- unique(df$site) 
plot.list <- sapply(sites, function(s) { 
    main.plot = ggplot(df[which(df$site == s),], aes(x=y)) + geom_histogram(colour="black", fill="gray") + scale_y_continuous(limits=c(0,1.5*ymax)) 
    main.plot.info = ggplot_build(main.plot) 
    xmin = min(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)]) 
    xmax = max(main.plot.info$data[[1]]$x[which(main.plot.info$data[[1]]$PANEL == 1)]) 
    sub.plot = ggplotGrob(ggplot(df[which(df$site == s),], aes(x=site_subjects)) + geom_bar() + theme_bw(base_size=9)) 
    return(ggplotGrob(main.plot + annotation_custom(grob = sub.plot, xmin = xmin, xmax = xmax, ymin=0.8*ymax, ymax=1.2*ymax)))}) 

grid.arrange(grobs=plot.list, ncol=3) 
Смежные вопросы