user11418708
user11418708

Reputation: 902

Drawing a back-to-back plot

I would like to draw a side-by-side plot, but I don't know how to specify the common x and y-axis please see the below plot. Also, I don't know how to adjust the values (counts) at the end of the bar charts. Also, how can fix the x-axis to 300 counts?

enter image description here

I found an example using R (but not ggplot) from here, can anyone give me some hint on doing this using ggplot? Thanks!

Sample data:

df1<-structure(list(Day = structure(c(5L, 1L, 6L, 7L, 4L, 2L), .Label = c("Monday", 
"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
), class = "factor"), counts = c(178L, 55L, 131L, 116L, 164L, 
96L)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"
))

df2<-structure(list(Day = structure(c(5L, 1L, 6L, 7L, 4L, 2L), .Label = c("Monday", 
"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
), class = "factor"), counts = c(244L, 120L, 264L, 198L, 223L, 
163L)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"
))

Code used:

rm(list = ls())

library(data.table)
library(reshape2)
library(ggplot2)
library(dplyr)
library(gridExtra)



Less <- read_dta("Data/Less.dta")
More <- read_dta("Data/More.dta")

df1 <- Less%>%
  group_by(Day) %>%
  summarise(counts = n())
df1

df1$Day <- factor(df1$Day,levels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))

g1<-ggplot(df1, aes(x = df1$Day, y = counts)) +
  geom_bar(fill = "#0073C2FF", stat = "identity") +
  geom_text(aes(label = counts), vjust = -0.3) + 
  labs(x="Day of the week", y ="Count", fill="", title="Time")  +
  theme(plot.title = element_text(hjust = 0.5, size=15))+ theme(axis.text.x = element_text(angle = ,family="Times", face="bold", size=15), axis.title.y = element_text(size = 15),axis.text.y = element_text(size=15, face="bold")) + theme(axis.title.y = element_text(size = 15)) + theme(axis.title.x = element_text(size = 15),plot.margin = unit(c(1,0,1,0), "mm")) +
  theme(legend.position = "bottom", legend.key.width = unit(8, "cm"), legend.text=element_text(size=15))+
  scale_y_reverse()+coord_flip()
g1
###############

df2 <- More %>%
  group_by(Day) %>%
  summarise(counts = n())
df2

df2$Day <- factor(df2$Day,levels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))

g2<-ggplot(df2, aes(x = df2$Day, y = counts)) +
  geom_bar(fill = "#0073C2FF", stat = "identity") +
  geom_text(aes(label = counts), vjust = -0.3) + 
  labs(x="Day of the week", y ="Count", fill="", title="Time")  +
  theme(plot.title = element_text(hjust = 0.5, size=15))+ theme(axis.text.x = element_text(angle = ,family="Times", face="bold", size=15), axis.title.y = element_text(size = 15),axis.text.y = element_text(size=15, face="bold")) + theme(axis.title.y = element_text(size = 15)) + theme(axis.title.x = element_text(size = 15), plot.margin = unit(c(1,5,1,0), "mm")) +
  theme(legend.position = "bottom", legend.key.width = unit(8, "cm"), legend.text=element_text(size=15))+
   coord_flip()
g2

grid.arrange(g1, g2,
             widths=c(0.4, 0.4), ncol=2)

Upvotes: 0

Views: 257

Answers (1)

teunbrand
teunbrand

Reputation: 38023

This seems like facets might do the job but the difficulty is getting the first x-axis in reverse and the other not. One option is to use ggh4x::facetted_pos_scales() to do the axes (disclaimer I'm the author of ggh4x).

In the example below, assume df1 and df2 are your sample data. I've kept the code somewhat more minimal than your example for brevity reasons.

library(ggplot2)
library(ggh4x)

# Combine data.frames
all_df <- rbind(cbind(df1, facet = "Left"),
                cbind(df2, facet = "Right"))

ggplot(all_df, aes(counts, forcats::fct_rev(Day))) +
  geom_col() +
  geom_text(aes(label = counts),
            nudge_x = 15) +
  facet_wrap(~ facet, scales = "free_x") +
  facetted_pos_scales(x = list(
    scale_x_reverse(limits = c(300, 0)),
    scale_x_continuous(limits = c(0, 300))
  ))

Upvotes: 3

Related Questions