Home > Back-end >  Horizontal bar chart split by categories
Horizontal bar chart split by categories

Time:03-20

I have the following data frame

A <- c(2020, 2020, 2020, 2021, 2021, 2021)
B <- c("category 1", "category 2", "category 3", "category 1", "category 2", "category 3")
C <- c(7, 10, 5, 11, 8, 7)

data <- data.frame(A, B, C)
names(data) <- c("yeat", "categories", "value")

How can I plot a horizontal bar chart, that will look like this (i.e., the categories are sorted by their values for each year):

horizental bar chart

CodePudding user response:

Use barplot in an lapply. split the data by year and plot the values according to their order. We also give the bars col=ors according to this scheme as well as labels using mtext.

Colors and labels may be conveniently stored in a matrix m with row names by categories that we can easily match later.

(m <- matrix(c('#3C79A7', '#8ECBE9', '#FB4C58',
              "Category 1", "Category 2", "Category 3"), 3, 2,
            dimnames=list(sort(unique(data$categories)), NULL)))
#                    [,1]      [,2]        
# category 1 "#3C79A7" "Category 1"
# category 2 "#8ECBE9" "Category 2"
# category 3 "#FB4C58" "Category 3"

S <- split(data, data$year)
    
op <- par(mfrow=c(1, 2), mar=c(2, 6, 4, 2))  ## par: 2 plots, expand margins

lapply(names(S), \(x) {
  s <- S[[x]]
  u <- order(s$value)
  barplot(s$value[u], horiz=TRUE, col=m[s$categories[u], 1], border=NA,
          main=x[1], xaxt='n', yaxt='n', ylab='')
  mtext(m[s$categories[u], 2], 2, 1, at=seq_len(nrow(s)), las=2)
})

par(op)  ## reset pars

enter image description here


Data:

data <- structure(list(year = c(2020, 2020, 2020, 2021, 2021, 2021), 
    categories = c("category 1", "category 2", "category 3", 
    "category 1", "category 2", "category 3"), value = c(7, 10, 
    5, 11, 8, 7)), class = "data.frame", row.names = c(NA, -6L
))

CodePudding user response:

You can use this code:

library(tidyverse)
library(forcats)
library(patchwork)
A <- c(2020, 2020, 2020, 2021, 2021, 2021)
B <- c("category 1", "category 2", "category 3", "category 1", "category 2", "category 3")
C <- c(7, 10, 5, 11, 8, 7)

data <- data.frame(A, B, C)
names(data) <- c("yeat", "categories", "value")

p1 <- data %>%
  filter(yeat == 2020) %>%
  mutate(categories = fct_reorder(categories, value)) %>%
  ggplot(aes(x = categories, y = value))  
  geom_col()  
  xlab("Categories")  
  ylab("")  
  ggtitle("2020")  
  coord_flip()  
  theme(legend.position = "none")

p2 <- data %>%
  filter(yeat == 2021) %>%
  mutate(categories = fct_reorder(categories, value)) %>%
  ggplot(aes(x = categories, y = value))  
  geom_col()  
  xlab("Categories")  
  ylab("")  
  ggtitle("2021")  
  coord_flip()  
  theme(legend.position = "none")

p1   p2

Output:

enter image description here

CodePudding user response:

How about using enter image description here

The definitions of the custom colors are shamelessly stolen from enter image description here

  • Related