Home > other >  Conditional (row-wise) formating of currency, number, and percentage in R DT (datatable)
Conditional (row-wise) formating of currency, number, and percentage in R DT (datatable)

Time:07-06

I have column in my DT output (in Shiny) that has a numeric value whose units depend on another column. Some values are percentages, some are currency, and some are plain numbers.

For example, I would like to turn this input...

DefaultFormat Value
PCT 12345.67
DOLLAR 12345.67
NUMBER 12345.67

...into this DT output:

DefaultFormat Value
PCT 123.45%
DOLLAR $12,345
NUMBER 12,345.67

The formatCurrency(), formatPercentage() and formatRound() functions do what I need for each of these respective formats but they affect the entire column instead specific cells. On the other hand formatStyle() can target specific cells in a column based on another column but I can't figure out a way to have it change the contents rather than the styles.

Furthermore, I tried setting the class using formatStyle() in the hopes that in the .css file I could then target, e.g. .pctclass:after and .currencyclass:before but it ignores the class attribute.

What is a good way to get the conditional behavior of formatStyle() but for numbers, percentages, and currencies?

CodePudding user response:

(This is not DT-specific, it wasn't clear if that was a requirement.)

You can group or split and assign:

library(dplyr)
set.seed(2)
dat <- data.frame(fmt = sample(c("PCT","DOLLAR","NUMBER"), 10, replace = TRUE), value = round(runif(10, 10, 9999), 2))

dat %>%
  group_by(fmt) %>%
  mutate(value2 = switch(fmt[1],
    PCT=scales::percent(value),
    DOLLAR=scales::dollar(value),
    NUMBER=scales::percent(value),
    as.character(value))
  )
# # A tibble: 10 x 3
# # Groups:   fmt [3]
#    fmt    value value2   
#    <chr>  <dbl> <chr>    
#  1 PCT    1816. 181 621% 
#  2 NUMBER 4058. 405 836% 
#  3 DOLLAR 8536. $8,536.10
#  4 DOLLAR 9763. $9,763.24
#  5 PCT    2266. 226 577% 
#  6 PCT    4453. 445 320% 
#  7 PCT     759. 75 897%  
#  8 PCT    6622. 662 171% 
#  9 PCT    3881. 388 123% 
# 10 DOLLAR 8370. $8,369.69

An alternative would be to use case_when and it would come up with very similar results, but it will be working one string at a time; this method calls the format function once per group, perhaps a bit more efficient. (Over to you if that's necessary.)

CodePudding user response:

EDIT: here's a solution borrowing from the approach here: enter image description here

  •  Tags:  
  • r dt
  • Related