celilati
celilati

Reputation: 165

R ggplot: Combine a barplot and a line chart from a long dataset

I have a wide dataset that records the blood glucose values from 10 subjects.

library(dplyr) 

df_wide = data.frame(
  ID = seq(1, 10),
  gender = sample(0:1, 10, replace = T),
  glucose_0 = sample(100:125, 10, replace = T),
  glucose_60 = sample(180:200, 10, replace = T),
  glucose_120 = sample(130:160, 10, replace = T),
  glucose_180 = sample(100:125, 10, replace = T)
) 

I then transformed it into a long dataset using gather:

df_long = df_wide %>% 
  gather("glucose_0", "glucose_60", "glucose_120", "glucose_180", key = Time, value = glucose) %>% 
  arrange(ID)

To show how the glucose values changed from 0 min to 180 min, I then made the following line chart:

df_long %>% 
  ggplot(aes(x = Time, y = glucose, group = ID)) + 
  geom_line(aes(linetype = as.factor(gender))) +
  geom_point() +
  theme_classic() +
  scale_x_discrete(limits = c("glucose_0", "glucose_60", "glucose_120", "glucose_180"),
                   labels = c("0", "60", "120", "180")) +
  theme(legend.position = "bottom") +
  labs(
    x = "Time",
    y = "Glucose",
    fill = "Gender"
  ) 

Finally, to show the glucose at each time point, I also made a barplot:

df_long %>% 
  ggplot(aes(x = Time, y = glucose, fill = as.factor(gender))) + 
  geom_bar(stat = 'identity', position = position_dodge()) +
  theme_classic() +
  scale_x_discrete(limits = c("glucose_0", "glucose_60", "glucose_120", "glucose_180")) 

My question is: How to combine the line chart and the barplot into one figure that looks like this? Goal

Upvotes: 1

Views: 71

Answers (2)

langtang
langtang

Reputation: 24722

In order to plot the mean glucose levels as both bar and line

df_long %>%
  group_by(gender, Time) %>% 
  mutate(glucose = mean(glucose)) %>% 
  ggplot(aes(x = Time, y = glucose, fill = as.factor(gender))) + 
  geom_bar(stat = 'identity', position = position_dodge()) +
  geom_line(aes(linetype=as.factor(gender), group=ID)) +
  theme_classic() +
  scale_x_discrete(limits = c("glucose_0", "glucose_60", "glucose_120", "glucose_180")) 

enter image description here

Upvotes: 1

TarJae
TarJae

Reputation: 78927

Are you looking for such a solution?

library(tidyverse)

df_wide %>% 
  pivot_longer(
    starts_with("glucose")
  ) %>% 
  mutate(gender = fct_inorder(factor(gender))) %>% 
  arrange(ID) %>% 
  ggplot(aes(x = name, y = value)) + 
  geom_col(aes(fill = gender, group=gender), width = 0.5, position = position_dodge())+
  stat_summary(aes(group = gender), fun = mean, geom = 'line', size=1, alpha=0.9) +
  stat_summary(aes(group = gender), fun = mean, geom = 'point', size=2, alpha=0.9) +
  theme_classic() +
  scale_x_discrete(limits = c("glucose_0", "glucose_60", "glucose_120", "glucose_180"),
                   labels = c("0", "60", "120", "180")) +
  theme(legend.position = "bottom") +
  labs(
    x = "Time",
    y = "Glucose",
    fill = "Gender"
  ) 

enter image description here

Upvotes: 1

Related Questions