stacked bar chart in r using ggplot

Viewed 80

I want to analysis covid situation for 2020 vs 2021 and want to show how contagious virus in 2021 using ggplot

df <- data.frame(
  self_impact = as.factor(c("Y", "Y", "Y", "N", "N", "Y", "Y", "Y", "Y", "N")),
  impacted_family = c("4", "0", "5", "1", "2", "0", "3", "0", "2", "2"),
  month = c(
    "Jan-21", "Jan-21", "Feb-21", "Jan-21", "Mar-21", "Mar-21", "Apr-21",
    "Oct-20", "Nov-20", "Dec-20"
  )
)
self_impact impacted_family  month
        Y               4    Jan-21
        Y               0    Jan-21
        Y               5    Feb-21
        N               1    Jan-21
        N               2    Mar-21
        Y               0    Mar-21
        Y               3    Apr-21
        Y               0    Oct-20
        Y               2    Nov-20
        N               2    Dec-20

For year 2020 there are 2 self_impact vs 2021 with 5 self impact.

Of these 2 self impact in 2020 one family got infected whereas in 2021 out of 5 self impact 3 family were infected.

Also the number of impacted family member is very high in 2021 vs 2020.

I want to show this three information in stacked bar chart using ggplot with some color option for each year.

Any help is useful, Thanks!

2 Answers

Its ideal to avoid 3 dimensions as folks tend to lose their way across >2 dimensions. Its ideal to plot 2 charts one each for self_impact.

Nevertheless, you can summarize your data frame by the year + self_impact and then plot with facet_wrap to showcase 3 dimension as follows.

df%>%
  mutate(year2= year(dmy(paste0("01-",month))))%>% # getting to char date->year
  select(-month)%>% # removing since redundant.
  group_by(year2,self_impact)%>%
  summarise(impacted_family = sum(as.numeric(impacted_family)),
            self_impact2 = n())%>% # summarizing the data
  ungroup()%>%
  ggplot()+
  aes(as.factor(year2),impacted_family)+
  geom_col(color=NA)+
  facet_wrap(~self_impact)

A way to do this is a line chart with color by the self_impact like this

Simply just graph the data monthly

library(lubridate)
library(tidyverse)


# Graph by month
monthly_summary_data <- df %>%
  mutate(month_formatted = as.Date(paste("01 ", month), format = "%d %b-%y")) %>%
  # getting to char date->year
  # removing since redundant.
  group_by(month_formatted, self_impact) %>%
  summarise(
    impacted_family = sum(as.numeric(impacted_family)),
    self_impact2 = n(),
    .groups = "drop"
  )

# As we can see the data is not very much and the plot at month level is just
# noise
ggplot(data = monthly_summary_data) +
  geom_line(aes(x = month_formatted, y = impacted_family,
    group = self_impact, color = self_impact))

Or graph the data yearly to reduce noise but lacking the detail

# Graph by year
year_summary_data <- df %>%
  mutate(year =
      factor(year(as.Date(paste("01 ", month), format = "%d %b-%y")))) %>%
  # getting to char date->year
  # removing since redundant.
  group_by(year, self_impact) %>%
  summarise(
    impacted_family = sum(as.numeric(impacted_family)),
    self_impact2 = n(),
    .groups = "drop"
  )

# With the sample amount of data a year level graph is better
ggplot(data = year_summary_data) +
  geom_line(aes(x = year, y = impacted_family,
    group = self_impact, color = self_impact)) +
  # Set y axis to start from ZERO
  scale_y_continuous(limits = c(0, NA))

Using cumsum figures to reduce noise from monthly graph & compare between year with linetype for year variable

year_month_summary <- df %>%
  mutate(date = as.Date(paste("01 ", month), format = "%d %b-%y"),
    year = factor(year(date)),
    month = month(date)) %>%
  # getting to char date->year
  # removing since redundant.
  group_by(year, month, self_impact) %>%
  summarise(
    impacted_family = sum(as.numeric(impacted_family)),
    .groups = "drop") %>%
  group_by(year, self_impact) %>%
  mutate(cum_impacted_family = cumsum(impacted_family))

# Using the cumsum to reduce the noise by month 
# and added the linetype using year variable provide some comparison 
ggplot(data = year_month_summary) +
  geom_line(aes(x = month, y = cum_impacted_family,
    group = paste0(year, self_impact), color = self_impact, linetype = year)) +
  # Set y axis to start from ZERO
  scale_y_continuous(limits = c(0, NA)) +
  scale_x_continuous(breaks = seq(1, 12, by = 1), expand = c(0, 0))

Created on 2021-04-20 by the reprex package (v2.0.0)

Related