whichColumnsAreCurrency <- function(DT, curr.symbol="$", sample_size=1e5) {

    pat.curr <- paste0("^\\s*", regOr(curr.symbol, escape=TRUE))
    inds <- if (nrow(DT) <= sample_size * 1.1) TRUE else sort(sample(nrow(DT), sample_size, FALSE))
    DT[inds, sapply(.SD, function(col) any(suppressWarnings(grepl(pat.curr, col))))] %>% which %>% names
}

convertCurrencyColumnsToNumeric_ <- function(DT, colsToConvert=whichColumnsAreCurrency(DT), NA.string=c("NA", "#N/A"), curr.symbol="$", comma=",", clean_excel_zeros=TRUE) {
  if (length(colsToConvert))
    DT[, (colsToConvert) := lapply(.SD, currToNumeric, NA.string=NA.string, curr.symbol=curr.symbol, comma=comma, clean_excel_zeros=clean_excel_zeros), .SDcols=colsToConvert]
  return(invisible(DT))
}

currToNumeric <- function(x, NA.string=c("NA", "#N/A"), curr.symbol="$", comma=",", clean_excel_zeros=TRUE) {
## removes '$' and ',' commas
##  and replaces parens with negatives.
## excel_zeros are usually "  $ -  " 
  if (is.data.table(x)) {
    return(x[, lapply(.SD, currToNumeric)])
  } 

  if (is.data.table(x)) {
    stop("To clean currency columns of a data.table, use convertCurrencyColumnsToNumeric_(DT)")
  }
  if (is.twodim(x)) {
    dimx <- dim(x)
    ret <- apply(x, 2, currToNumeric)
    dim(ret) <- dimx
    if (is.data.frame(x))
      ret <- as.data.frame(ret)
    return(ret)
  }

  if (is.numeric(x))
    return(x)

  if (is.factor(x))
    x <- as.character(x)

  ## Clean NAs
  if (!is.null(NA.string))
    x[x %in% NA.string] <- NA

  if (clean_excel_zeros) {
    pat.excel <- paste0("^\\s*", regOr(curr.symbol, escape=TRUE), "\\s*-\\s*$")
    x <- gsub(pat.excel, "0", x)
  }
  ## OLD: 
  # return(as.numeric(gsub("\\((.*)\\)", "-\\1", gsub("\\$|,", "", col))))
  pat_to_clear <- regOr(c(curr.symbol, comma), escape=TRUE)
  pat_to_negative <- "\\((.*)\\)"
  x %>% gsub(pat_to_clear, "", .) %>% 
        gsub(pat_to_negative, "-\\1", .) %>% 
        as.numeric
}