1

I'm trying to get a facet-grid of my data-frame.

The purpose is to summarize the composition (in percent) of each clades (A, B, C, D, E, F) for every individuals (n=24).

Also the sum of each clade is not 100%, but ultimately really close to it. None of the individuals got Clade B or F.

Here is my R script :

library(scales)
library(reshape)
library(ggplot2)

#Add an id variable for the filled regions
X_clade$ind <- factor(X_clade$ind)
X_clade$days <- factor(X_clade$days)
X_clade$temperature <- factor(X_clade$temperature)
X_clade$D <- NULL
Clade <- c(X_clade$A, X_clade$B, X_clade$C, X_clade$E, X_clade$F)
Abundance= 100*cumsum(Clade)/sum(Clade)
str(X_clade)
Abundance
hist(Clade$A)

#subset
file.29<-X_clade[(X_clade$days == 29),]
file.65<-X_clade[(X_clade$days == 65),]
file.53<-X_clade[(X_clade$days == 53),]

#install.packages("wesanderson")
library(wesanderson)
plot_bar(X_clade)

file.29$B <- NULL
file.29$F <- NULL
seq(0.1,1,by=0.1)

p1<-ggplot(file.29,aes(x = ind, y=Abundance,fill = Clade)) +
  geom_bar(position = "fill",stat = "identity") +    
  scale_y_continuous(labels = percent_format())  +
  theme(panel.background = element_blank(),
        panel.border=element_rect(fill=NA),
        panel.grid.minor = element_blank(),
        axis.text.x=element_text(colour="black",size=11),
        axis.text.y=element_text(colour="black",size=11),
        axis.title =element_blank()) + guides(fill=FALSE) +
  facet_grid(days~temperature,scales="free_x")
p1

p_1M=ggplot(file.29,aes(x = ind, y=Abundance,fill = Clade)) 
p_1M

p2<-ggplot(file.53,aes(x = ind, y=Abundance,fill = Clade)) +
  geom_bar(position = "fill",stat = "identity") +  
  scale_y_continuous(labels = percent_format())  +
  theme(panel.background = element_blank(),
        panel.border=element_rect(fill=NA),
        panel.grid.minor = element_blank(),
        strip.text.x = element_blank(),
        axis.text.x=element_text(colour="black",size=11),
        axis.text.y=element_text(colour="black",size=11),
        axis.title =element_blank()) +guides(fill=FALSE) +
  facet_grid(days~temperature,scales="free_x")
p2

p3<-ggplot(file.65,aes(x = ind, y=Abundance,fill = Clade)) +
  geom_bar(position = "fill",stat = "identity") +  
  scale_y_continuous(labels = percent_format())  +
  theme(panel.background = element_blank(),
        panel.border=element_rect(fill=NA),
        panel.grid.minor = element_blank(),
        strip.text.x = element_blank(),
        axis.text.x=element_text(colour="black",size=11),
        axis.text.y=element_text(colour="black",size=11),
        axis.title =element_blank()) + guides(fill=FALSE) +
  facet_grid(days~temperature,scales="free_x")
p3

library(gridExtra)

grid.arrange(p1, p2, p3, nrow=3)

but for each plot (p1,p2,p3), i get the same error message : Error: Aesthetics must be either length 1 or the same as the data (8): x, y, fill.

Every insight on how to resolve this issue would be lovely ! As I am sure I'm not far away from it. But still, all the way stuck tho !

All my best

Homère

Homère
  • 13
  • 3

2 Answers2

1

One solution could be to plot the data using facet_wrap turn off the strip labels and add desired labels using inkscape or photoshop.

library(tidyverse)
d %>% 
  gather(k, v, -days, -ind, -temperature) %>%
  ggplot(aes(x = factor(ind), y=v, fill = k)) +
  geom_col() +
  scale_y_continuous(labels = function(x) paste0(x, "%"))  +
  facet_wrap(~temperature + days, scales="free_x", dir = "v", ncol=2) + 
  theme(strip.text = element_blank(),
        legend.position = "bottom")

enter image description here

Or try this

p1 <- d %>% 
  gather(k, v, -days, -ind, -temperature) %>% 
  filter(days == 29) %>% 
  ggplot(aes(x = factor(ind), y=v, fill = k)) +
  geom_col() +
  scale_y_continuous(labels = function(x) paste0(x, "%"))  +
  facet_grid(days~temperature, scales="free_x")+
  xlab("") + 
  theme(legend.position = "none")

p2 <- d %>% 
  gather(k, v, -days, -ind, -temperature) %>% 
  filter(days == 53) %>% 
  ggplot(aes(x = factor(ind), y=v, fill = k)) +
  geom_col() +
  scale_y_continuous(labels = function(x) paste0(x, "%"))  +
  facet_grid(days~temperature, scales="free_x")+
  xlab("") + 
  theme(strip.text.x = element_blank(),
        legend.position = "none")

p3 <- d %>% 
  gather(k, v, -days, -ind, -temperature) %>% 
  filter(days == 65) %>% 
  ggplot(aes(x = factor(ind), y=v, fill = k)) +
  geom_col() +
  scale_y_continuous(labels = function(x) paste0(x, "%"))  +
  facet_grid(days~temperature, scales="free_x")+
  theme(strip.text.x = element_blank(),
        legend.position = "none")

p4 <- d %>% 
  gather(k, v, -days, -ind, -temperature) %>% 
  ggplot(aes(x = factor(ind), y=v, fill = k)) +
  geom_col() +
  theme_void()

library(cowplot)         
cowplot::plot_grid(plot_grid(p1, p2, p3, ncol = 1), get_legend(p4), rel_widths = c(0.9,0.1))

enter image description here

Roman
  • 17,008
  • 3
  • 36
  • 49
0

Here's a version that combines purrr with cowplot to make a list of plots and arrange them together. I'm mimicking a facet_grid by splitting the data on temperature, making separate columns of plots with facet_wrap. Using imap, I get the name of each of the split data frames—the temperature—and use this for titles. Then I do some slightly hacky things to extract the legend, remove the legend from both plots, make the strip text on the left plot invisible, and plot them all alongside each other.

library(tidyverse)


df2 <- df %>%
  mutate_at(vars(days, temperature, ind), as.factor) %>%
  gather(key = group, value = value, -ind, -days, -temperature) %>%
  mutate(value = value / 100)

plots <- df2 %>%
  split(.$temperature) %>%
  imap(function(dat, temp) {
    ggplot(dat, aes(x = ind, y = value, fill = group)) +
      geom_col() +
      scale_y_continuous(labels = scales::percent) +
      scale_fill_discrete(drop = T) +
      labs(x = NULL, y = NULL) +
      facet_wrap(~ days, ncol = 1, scales = "free_x", strip.position = "right") +
      theme_minimal() +
      theme(strip.text.y = element_text(angle = 0, face = "italic"), 
            plot.title = element_text(hjust = 0.5, face = "italic")) +
      ggtitle(paste0(temp, "°C"))
  })

For example, the first column of plots looks like this:

plots[[1]]

I made the strip text on the first column white to match the strip background, because I wanted it to still take up some space (so the columns would still have the same width) but not be visible.

legend <- cowplot::get_legend(plots[[1]])
no_legends <- plots %>% map(~. + theme(legend.position = "none"))
no_legends[[1]] <- no_legends[[1]] + theme(strip.text = element_text(color = "white"))

Using cowplot and following one of its vignettes, I made one grid of the two plots without legends, and a second grid of that first grid plus the legend, and adjust the relative widths to fit nicely. There's a lot of spacing and tweaking you can do from here.

two_plots <- cowplot::plot_grid(plotlist = no_legends)
cowplot::plot_grid(two_plots, legend, rel_widths = c(2, 0.25))

Created on 2018-05-25 by the reprex package (v0.2.0).

camille
  • 16,432
  • 18
  • 38
  • 60
  • Hello Camille, I runned it and it's perfect. That's really nice of you ! A quick follow, I would like to change colors of each Clade (A,B,C,E,F) for a wesanderson palette, "IsleofDogs2". – Homère May 25 '18 at 20:14
  • You can add `scale_fill_*`, where `*` is whatever the name of the fill function is. I haven't used that package, but it should ship with some sort of scales like that, I'd assume – camille May 25 '18 at 20:42