r-lib / prettyunits

Pretty, human readable formatting of quantities
http://r-lib.github.io/prettyunits/
Other
132 stars 15 forks source link

Add support for monetary amounts. #7

Open shabbychef opened 9 years ago

shabbychef commented 9 years ago

I often have to render monetary amounts in tables that span multiple orders of magnitude. It would be nice if there were a way to 'pretty print' these sanely, so e.g. 1357 would render as "$1.36 K", 5.5e7 renders as "$55 M", and so on. I've written one-off code that does it, but would prefer it live in some canonical package, like this one.

shabbychef commented 9 years ago

Perhaps the following is a decent place to start:

pretty_money <- function(dollars, digits=2, suffixes=c('','K','M','B')) {
    n_commas <- pmin(floor(floor(log10(pmax(1,abs(dollars)))) / 3),
                                     length(suffixes)-1)
    retv <- paste0('$',
                                    signif(dollars,digits=digits) / (10^(3*(n_commas))),
                                    suffixes[n_commas+1])
}
print(pretty_money(c(0.01,-100,2.3e3,9.9e5,1e6,1.5e10)))
[1] "$0.01" "$100"  "$2.3K" "$990K" "$1M"   "$15B" 

(sorry, I use ts=2 in vim, not 8)

Probably this has to be modified to deal with the `compact' argument, as well as different currencies. There is also the convention of wrapping negative amounts in parens, which could be useful.

gaborcsardi commented 9 years ago

Great idea! It does not necessarily need a compact argument, only if we want rounding. Let me look over the various ways people write dollars.

Btw. why is the K uppercase, I guess it stands for kilo, which is lowercase. Doesn't it?

shabbychef commented 9 years ago

Good catch wrt k vs K, I believe you are right. Perhaps the compact argument should determine whether there is a space between the $ and the number?

I am also guessing that some users would prefer that 1350 render as $1,350 instead of $1.35 k. Perhaps there should be some accommodation for that by setting the corresponding element of suffixes to NA. But maybe that's too fancy.

There's a Javascript library which does many of these conversions. You may want to look into their solutions for reference.