'Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, : invalid value 0 for 'digits' argument

When I submit priceR to R-hub, I see the following logs:

### ** Examples
> 
> 
> format_currency("2423562534234", "$")
Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L,  : 
  invalid value 0 for 'digits' argument
Calls: format_currency ... sub -> is.factor -> format -> format.default -> prettyNum
Execution halted
* checking for unstated dependencies in ‘tests’ ... OK
* checking tests ...
  Running ‘testthat.R’
 ERROR
Running the tests in ‘tests/testthat.R’ failed.
Last 13 lines of output:
    7. ├─base::paste0(symbol, .)
    8. ├─base::trimws(.)
    9. │ ├─base:::mysub(...)
   10. │ │ └─base::sub(re, "", x, perl = TRUE)
   11. │ │   └─base::is.factor(x)
   12. │ └─base:::mysub(paste0("^", whitespace, "+"), x)
   13. │   └─base::sub(re, "", x, perl = TRUE)
   14. │     └─base::is.factor(x)
   15. ├─base::format(...)
   16. └─base::format.default(...)
   17.   └─base::prettyNum(...)
  
  [ FAIL 4 | WARN 0 | SKIP 0 | PASS 30 ]
  Error: Test failures
  Execution halted

What causes the error?

The logs say format_currency("2423562534234", "$") causes the error.

format_currency() is defined as:


library(tidyverse) 

format_currency <- function(amount, symbol, digits) {

  if(missing(digits)) { digits <- 0 }

  symbol_regex <- gsub("([.|()\\^{}+$*?]|\\[|\\])", "\\\\\\1", symbol)

  amount %>%
    gsub(",", "", .) %>%
    as.numeric %>%
    round(., digits) %>%
    format(big.mark = ",", digits = digits, scientific = FALSE, nsmall = digits) %>%
    trimws %>%
    paste0(symbol, .)

}

# Example usage
format_currency("2423562534234", "$")
# "$2,423,562,534,234"

What I've tried

?format says:

used for prettying (longish) numerical and complex sequences. Passed to prettyNum: that help page explains the details.

I tried changing if(missing(digits)) { digits <- 0 } to if(missing(digits)) { digits <- 0L } but the same error persisted.

Note that the time to try new things is very slow because the package has to be built the submitted to R-hub, which takes around 6-10 minutes to reproduce the build and eventually the error (if someone's running linux, they may be able to reproduce locally for much faster attempts to fix! - unfortunately I presently do not have access to a linux machine).

Any ideas?

Further attempts

Thanks to @Onyambu's suggestion to try digits <- 1 as a default in format_currency(). With this default, it looks like the examples/tests will pass. But instead of producing "$2,423,562,534,234", it now produces "$2,423,562,534,234.0", which is undesirable. But it does show that changing the digits value to some positive integer alleviates the error.

* checking examples ... ERROR
Running examples in ‘priceR-Ex.R’ failed
The error most likely occurred in:

> ### Name: format_currency
> ### Title: Make numeric currency values human readable
> ### Aliases: format_currency
> 
> ### ** Examples
> 
> 
> format_currency("2423562534234", "$")
[1] "$2,423,562,534,234.0"
> # "$2,423,562,534,234"
> 
> format_currency("2423562534234.876", "$", 0)
Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L,  : 
  invalid value 0 for 'digits' argument
Calls: format_currency ... sub -> is.factor -> format -> format.default -> prettyNum
Execution halted

Update: Closing the case (for now)

For future reference, this was the last set of error logs. Note from the relevant excerpt that I can't tell which test failed, just that at least one of them did fail - this makes fixing the problem impractically slow when taking this approach:

* checking tests ...
  Running ‘testthat.R’
 ERROR
Running the tests in ‘tests/testthat.R’ failed.
Last 13 lines of output:
    6. ├─base::paste0(symbol, .)
    7. ├─base::trimws(.)
    8. │ ├─base:::mysub(...)
    9. │ │ └─base::sub(re, "", x, perl = TRUE)
   10. │ │   └─base::is.factor(x)
   11. │ └─base:::mysub(paste0("^", whitespace, "+"), x)
   12. │   └─base::sub(re, "", x, perl = TRUE)
   13. │     └─base::is.factor(x)
   14. ├─base::format(...)
   15. └─base::format.default(...)
   16.   └─base::prettyNum(...)
  
  [ FAIL 1 | WARN 0 | SKIP 0 | PASS 29 ]
  Error: Test failures
  Execution halted

The cycle time for making changes and checking is about 15 minutes, too slow to quick diagnosis and fixes. In the interest of efficacy, I'm omitting tests for this family of functions from the package to fit within CRAN requirements.

My plan in future is to investigate how to quickly spin up a cloud (AWS) instance so I can test with a much faster cycle time, hopefully just a few seconds between making a change and testing it on the operating system that produces the issues.

r


Solution 1:[1]

This a new ‘feature’ in R 4.1.*.

On the R News page, it says:

Setting digits = 0 in format(), print.default() (and hence typically print()) or options() is again invalid. Its behaviour was platform-dependent, and it is unclear what “zero significant digits” should mean (PR#18098).

Source: https://cran.r-project.org/doc/manuals/r-devel/NEWS.html

They call it a ‘bug fix’, but I think this is an utterly bad design choice. Setting digits to 0 makes perfectly sense to me. But unfortunately we have to keep ourselves from using it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1