Home > Software engineering >  Horizontal Group Bar Chart - How to scale to 100% and how to specify the order of the layers
Horizontal Group Bar Chart - How to scale to 100% and how to specify the order of the layers

Time:02-03

So I have the following code which produces:

enter image description here

The issue here is twofold:

  1. The group bar chart automatically places the highest value on the top (i.e. for avenue 4 CTP is on top), whereas I would always want FTP to be shown first then CTP to be shown after (so always blue bar then red bar)

  2. I need all of the values to scale to 100 or 100% for their respective group (so for CTP avenue 4 would have a huge bar graph but the other avenues should be extremely tiny)

I am new to 'R'/Stack overflow so sorry if anything is wrong/you need more but any help is greatly appreciated.

library(ggplot2)
library(tidyverse)
library(magrittr)

# function to specify decimals
specify_decimal <- function(x, k) trimws(format(round(x, k), nsmall=k))

# sample data
avenues <- c("Avenue1", "Avenue2", "Avenue3", "Avenue4")
flytip_amount <- c(1000, 2000, 1500, 250)
collection_amount <- c(5, 15, 10, 2000)

# create data frame from the sample data
df <- data.frame(avenues, flytip_amount, collection_amount)

# got it working - now to test

df3 <- df

SumFA <- sum(df3$flytip_amount)
df3$FTP <- (df3$flytip_amount/SumFA)*100
df3$FTP <- specify_decimal(df3$FTP, 1)

SumCA <- sum(df3$collection_amount)
df3$CTP <- (df3$collection_amount/SumCA)*100
df3$CTP <- specify_decimal(df3$CTP, 1)

# Now we have percentages remove whole values 

df2 <- df3[,c(1,4,5)]

df2 <- df2 %>% pivot_longer(-avenues)

FTGraphPos <- df2$name

ggplot(df2, aes(x = avenues, fill = as.factor(name), y = value))   
  geom_col(position = "dodge", width = 0.75)   coord_flip()   
  labs(title = "Flytipping & Collection %", x = "ward_name", y = "Percentageperward")   
  geom_text(aes(x= avenues, label = value), vjust = -0.1, position = "identity", size = 5)

I have tried the above and I have looked at lots of tutorials but nothing is exactly precise to what I need of ensuring the group bar charts puts the layers in the same order despite amount and scaling to 100/100%

CodePudding user response:

As Camille notes, to handle ordering of the categories in a plot, you need to set them as factors, and then use functions from the forcats package to handle the order. Here I am using fct_relevel() (note that it will automatically convert character variables to factors).

Your numeric values are in fact set to character, so they need to be set to numeric for the chart to make sense.

To cover point #2, I'm using group_by() to calculate percentages within each name.

I have also fixed the labels so that they are properly dodged along with the bar chart. Also, note that you don't need to call ggplot2 or magrittr if you are calling tidyverse - those packages come along with it already.

df_plot <- df2 |> 
  mutate(name = fct_relevel(name, "CTP"),
         value = as.numeric(value)) |> 
  group_by(name) |> 
  mutate(perc = value / sum(value)) |> 
  ungroup()

ggplot(df_plot, aes(x = value, y = avenues, fill = name))  
  geom_col(position = "dodge", width = 0.75)  
  geom_text(aes(label = value), position = position_dodge(width = 0.75), size = 5)  
  labs(title = "Flytipping & Collection %", x = "Percentageperward", y = "ward_name")  
  guides(fill = guide_legend(reverse = TRUE))

enter image description here

  • Related