MoranY
MoranY

Reputation: 51

extracting one facet from a ggplot

I have 2 plots, each showing a different type of data (vaccines, and illnesses), and I would like to extract segments of these plots to generate a plot per subject, that has both the vaccines and the illnesses, colored according to the original plot.

vac
  subject age  vaccine
1     E11 1.0 DTaP-IPV
2     E11 3.0 DTaP-IPV
3     E22 1.0 DTaP-IPV
4     E22 2.0     Rota
5     E22 3.0 DTaP-IPV
6     E22 3.3     Rota

ill
  subject age       illness
1     E11 0.5 ear infection
2     E11 2.0 ear infection
3     E22 0.8         fever
4     E22 1.2         fever
5     E22 3.0 ear infection

ggplot(vac,aes(x=age,y=subject,color=vaccine))+geom_point(size=5) +
  scale_color_brewer(palette="Set1",drop = FALSE)+facet_grid(subject~.)

OnlyVaccines

ggplot(ill,aes(x=age,y=subject,color=illness))+geom_point(size=5) +
  scale_color_brewer(palette="Set3",drop = FALSE)+facet_grid(subject~.)

OnlyFever

Now, I would like to have one figure for E11, that has one row of vaccines (colored in Set1 colors), and one row of illnesses (colored in Set3 colors), and the same for E22.

I have many data types, and ~40 subjects, so of course, I would like this done automatically, and not via illustrator, etc.

I think gtable is the way to go, but not sure how to extract one facet.

Thank you very much!

Upvotes: 4

Views: 1026

Answers (3)

eipi10
eipi10

Reputation: 93811

The code below combines vac and ill in a single data frame (adding a new variable type to distinguish vaccines from illnesses), which will allow us to plot both illnesses and vaccines in a single call to ggplot. The code is a bit clunky, but I'm hoping it gets you closer to what you're looking for.

library(RColorBrewer)
library(gridExtra)

# Combine data frames vac and ill by adding a new column 
# called "type" and changing name of the third column to "condition"
vac$type = "Vaccine"
names(vac)[3] = "condition"

ill$type = "Illness"
names(ill)[3] = "condition"

dat = rbind(vac, ill)

# Convert condition to a factor to get the levels ordered properly
dat$condition = factor(dat$condition, 
                       levels=c(unique(dat$condition[dat$type=="Vaccine"]), 
                                unique(dat$condition[dat$type=="Illness"])))

dat
   subject age     condition    type
1      E11 0.5 ear infection Illness
2      E11 2.0 ear infection Illness
3      E22 3.0 ear infection Illness
4      E22 0.8         fever Illness
5      E22 1.2         fever Illness
6      E11 1.0      DTaP-IPV Vaccine
7      E11 3.0      DTaP-IPV Vaccine
8      E22 1.0      DTaP-IPV Vaccine
9      E22 3.0      DTaP-IPV Vaccine
10     E22 2.0          Rota Vaccine
11     E22 3.3          Rota Vaccine

Now we generate one graph per subject, place each graph in a list, and then save all the graphs in a single PDF file. The ggplot code works as follows:

  • Facet by subject so that we get a strip with the subject's ID.
  • Facet by type, so that we get separate graphs for illness and vaccine.
  • Use the color palette created below to get the colors we want

pal1 = c(brewer.pal(n=3, name="Set1")[1:2], brewer.pal(n=3, name="Set3")[1:2])

p = list() 
for (i in unique(dat$subject)) { 
  p[[i]] = ggplot(dat[dat$subject==i,], 
                  aes(x=age, y=condition, colour=condition)) +
    geom_point(size=5) + 
    scale_color_manual(values=pal1, drop=FALSE) + 
    facet_grid(type ~ subject, scale="free") + ylab("") + 
   guides(colour=FALSE) 
}

pdf("plots.pdf", 9,5)
do.call("grid.arrange", p)  
dev.off()

And here's the graph: enter image description here

Upvotes: 1

Jaap
Jaap

Reputation: 83215

In the facets you created in your question, you have empty rows for the subjects not in the facet. Having ~40 subjects this will create facets with one filled row and 39 empty rows, which is probably not what you want.

An alternative solution:

# merging the dataframes together
dat <- merge(vac, ill, by=c("subject","age"), all=TRUE, sort=TRUE)

# creating the plot
ggplot() +
  geom_point(data=dat[!is.na(dat$vaccine),], aes(x=age, y=subject, fill=vaccine), size=10, shape=22) +
  geom_point(data=dat[!is.na(dat$illness),], aes(x=age, y=subject, color=illness), size=7, shape=17) +
  scale_fill_brewer(palette="Set1") +
  scale_color_brewer(palette="Set2") +
  theme_bw()

which gives: enter image description here

Upvotes: 1

Leo
Leo

Reputation: 1835

Here is a quick solution that might help you in the right direction. Give it a shot.

require(reshape2)
require(plyr)
dat <- melt(join(vac, ill, type="full"), id.vars = c("subject", "age"), na.rm=TRUE)

ggplot(dat, aes(x=age,y=variable, color=value))+geom_point(size=5) +
  scale_color_brewer(palette="Set1",drop = FALSE)+facet_grid(subject~.)

Upvotes: 1

Related Questions