Search code examples
rggplot2localeseparator

Indian Style thousand separator in ggplot2 chart axes


Indian style thousand separators are used like this. First separator at 3 digits (thousands) but thereafter separator at every two digits.

1
10
100
1,000
10,000
1,00,000
10,00,000
1,00,00,000
10,00,00,000

I know that I can change/format axes in ggplot2 chart by using scale_y_continuous(labels = scales::comma)

But how can I change the thousand separator placeholder in r ggplot2 chart axes according to Indian formats as described above.

A sample example

library(tidyverse)
iris %>%
  mutate(Petal.Length= Petal.Length*100000) %>%
  ggplot(aes(x= Species, y = Petal.Length)) +
  geom_col() +
  scale_y_continuous(labels = scales::comma)

Created on 2021-06-28 by the reprex package (v2.0.0)


Solution

  • You can define your own formatting function and supply this as the labels argument to scale_y_continuous(). Here is an example using the base prettyNum() function:

    library(ggplot2)
    
    indian_comma <- function(x) {
      
      # Format the number, first dividing by 10 to place the first comma at the 
      # right point
      out <- prettyNum(x %/% 10, big.interval = 2L, big.mark = ",", scientific = FALSE)
      out <- paste0(out, x %% 10)
      
      # Switch between formatted and un-formatted depending on the size of the
      # number
      ifelse(
        x < 1000, x, out
      )
      
    }
    
    iris %>%
      mutate(Petal.Length= Petal.Length*100000) %>%
      ggplot(aes(x= Species, y = Petal.Length)) +
      geom_col() +
      scale_y_continuous(labels = indian_comma)
    

    Indian comma example

    EDIT

    Here's an alternative implementation using regular expressions. On balance I think I prefer the first option for clarity, but this is quite elegant:

    indian_comma <- function(x) {
      x <- prettyNum(x, scientific = FALSE)
      gsub("(?<!^)(?=(\\d{2})+\\d$)", ",", x, perl = TRUE)
    }