2015-10-15 3 views
3

Я большой поклонник facet_wrap. Хотя быстро разбить большой кадр данных и построить несколько графиков и исследовать внутри R, это не всегда лучший инструмент для представления в бумажной или силовой точке. Я нахожусь впустую много времени с весами, ширинами бинов и размерами шрифтов и, в конечном счете, изменяя на inkscape сюжет.ggplot2: сохранить отдельные грани facet_wrap как отдельные объекты участка

Иногда я просто подбираю свой фрейм данных во множество фреймов данных и строю индивидуально для каждого. Позже присоединитесь к ним с multiplot или вручную.

Мне было интересно, может ли быть способ сделать вызов ggplot почти таким же образом (один большой df с столбцом факторов, используемый для огранки), или способ заставить ggplot читать что-то со списком данных разделенный моим фактором факела. Идеальный выход должен быть несколько одиночных участков, которые я буду редактировать позже Inkscape (и использовать free_y весы, чтобы сделать его менее болезненным)

Чтобы было ясно,

df<-mtcars 
ggplot(df,aes(df$mpg,df$disp,color=factor(cyl)))+ 
    geom_point(aes(df$mpg,df$disp))+ 
    facet_wrap(~cyl) 

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

ответ

5

Вы можете использовать lapply, чтобы создать список с одним участком для каждого значения cyl:

# Create a separate plot for each value of cyl, and store each plot in a list 
p.list = lapply(sort(unique(mtcars$cyl)), function(i) { 
    ggplot(mtcars[mtcars$cyl==i,], aes(mpg, disp, colour=factor(cyl))) + 
    geom_point(show.legend=FALSE) + 
    facet_wrap(~cyl) + 
    scale_colour_manual(values=hcl(seq(15,365,length.out=4)[match(i, sort(unique(mtcars$cyl)))], 100, 65)) 
}) 

Сложного scale_colour_manual аргумента является способом цвета маркеров точки так же, как они будут крашеными, если все значения cyl были включены в один звонок по номеру ggplot.

UPDATE: Чтобы адресовать ваши комментарии, как об этом:

# Fake data 
set.seed(15) 
dat = data.frame(group=rep(c("A","B","C"), each=100), 
       value=c(mapply(rnorm, 100, c(5,10,20), c(1,3,5)))) 

p.list = lapply(sort(unique(dat$group)), function(i) { 
    ggplot(dat[dat$group==i,], aes(value, fill=group)) + 
    geom_histogram(show.legend=FALSE, colour="grey20", binwidth=1) + 
    facet_wrap(~group) + 
    scale_fill_manual(values=hcl(seq(15,365,length.out=4)[match(i, sort(unique(dat$group)))], 100, 65)) + 
    scale_x_continuous(limits=range(dat$value)) + 
    theme_gray(base_size=15) 
}) 

Результат приведен ниже. Обратите внимание, что приведенный выше код дает вам одинаковый масштаб x на всех трех графиках, но не тот же y-масштаб. Чтобы получить один и тот же масштаб y, вы можете либо скорректировать его, как, скажем, scale_y_continuous(limits = c(0,35)), или вы можете найти максимальный счетчик программно для любой заданной ширины бина, а затем подайте это на scale_y_continuous.

# Arrange all three plots together 
library(gridExtra) 
do.call(grid.arrange, c(p.list, nrow=3)) 

enter image description here

+0

Да, я ищу для этого. Он выполняет эту работу, однако синтаксис является сложным, и мы просто делаем точечный граф. Я нашел этот https://github.com/guiastrennec/ggplus, хотя он не работает для R версии 3.2. –

+0

Мне удалось создать сюжет с этим конкретным сюжетом, но он сильно мучает ось x (это гистограмма, а не каждая грань имеет те же значения x, что и в подсчетах), какие-либо рекомендации по этому поводу? –

+0

Я использую и адаптирую этот код весь день :). Просто чтобы добавить что-то к большому ответу. Если x является фактором с NA для некоторых уровней, использование scale_x_discrete (..., drop = FALSE) решает проблему наличия одинаковых уровней x в каждом графике –