Search code examples
rggplot2facet-wrap

Text on facets interfering with changing facet order in ggplot2


Example data:

percents = c(10,20,30,40,50,60,70,80,90,100)
percent_cases = rep(percents, 10)
no_cases = sample(1:1000, 100)
no_lineages = no_cases/rnorm(10, 7)
df = as.data.frame(cbind(percent_cases, no_lineages, no_cases))

I'm trying to make a faceted plot where I'd like the facets to be in a non-alphabetical order, and contain text specific to the data in that facet. In this example, the facets should be ordered by the percent of cases sampled, and the text contains the inverse gradient of the lm line. I'm using R version 4.0.2 through RStudio with ggplot2 version 3.3.6.

When I use this code, the facets are in the correct order but the text overlaps:

library(ggplot2)

#add text to facets
V1 = rep(NA, length(percents))
for(i in 1:length(percents)){
  df2 = df[df$percent_cases == percents[i],]
  fit = lm(df2$no_lineages~df2$no_cases)
  cf = coef(fit)
  V1[i] = paste0("'",round(1/cf[2]), " cases per lineage'")
}

df3 = as.data.frame(cbind(percents, V1))
names(df3) = c("percent_cases", "V1")

#change facet order
df$percent_cases_f <- factor(df$percent_cases,levels=c(10,20,30,40,50,60,70,80,90,100))

#change facet titles
percent.labs <- c("10% cases observed", "20% cases observed", "30% cases observed",
                  "40% cases observed", "50% cases observed", "60% cases observed",
                  "70% cases observed", "80% cases observed", "90% cases observed",
                  "100% cases observed")
names(percent.labs) <- percents

#plot
p <- ggplot(data = df, aes(x = no_cases, y = no_lineages)) +
  geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x) +
  geom_point() + 
  xlab("No. cases observed") + ylab("No. lineages")+
  geom_text(data=df3, aes(x = 500, y = 150, label=V1), parse = TRUE, inherit.aes=FALSE) + 
  facet_wrap(percent_cases_f~., labeller = labeller(percent_cases_f = percent.labs)) +
  theme_bw() 
p

faceted ggplot plots, with overlapping text on each facet

If I change the df3 column name from "percent_cases" to "percent_cases_f" to match the facet, the text overlap problem is solved but the facets are back in alphabetical order:

the same plots with text now not overlapping, but facet order defaulted to alphabetical order

Any ideas on how to stop the text overlapping while preserving the facet order?


Solution

  • @teunbrand's suggestion fixed it: df3$percent_cases_f should also be a factor with the same levels as df$percent_cases_f

    df3 = as.data.frame(cbind(percents, V1))
    names(df3) = c("percent_cases", "V1")
    df3$percent_cases_f <- factor(df3$percent_cases,levels=c(10,20,30,40,50,60,70,80,90,100))