StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
401 lines
14 KiB
401 lines
14 KiB
4 years ago
|
function __commonjs(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; }
|
||
|
|
||
|
/**
|
||
|
* The library's settings configuration object.
|
||
|
*
|
||
|
* Contains default parameters for currency and number formatting
|
||
|
*/
|
||
|
var settings = {
|
||
|
symbol: '$', // default currency symbol is '$'
|
||
|
format: '%s%v', // controls output: %s = symbol, %v = value (can be object, see docs)
|
||
|
decimal: '.', // decimal point separator
|
||
|
thousand: ',', // thousands separator
|
||
|
precision: 2, // decimal places
|
||
|
grouping: 3, // digit grouping (not implemented yet)
|
||
|
stripZeros: false, // strip insignificant zeros from decimal part
|
||
|
fallback: 0 // value returned on unformat() failure
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Takes a string/array of strings, removes all formatting/cruft and returns the raw float value
|
||
|
* Alias: `accounting.parse(string)`
|
||
|
*
|
||
|
* Decimal must be included in the regular expression to match floats (defaults to
|
||
|
* accounting.settings.decimal), so if the number uses a non-standard decimal
|
||
|
* separator, provide it as the second argument.
|
||
|
*
|
||
|
* Also matches bracketed negatives (eg. '$ (1.99)' => -1.99)
|
||
|
*
|
||
|
* Doesn't throw any errors (`NaN`s become 0) but this may change in future
|
||
|
*
|
||
|
* ```js
|
||
|
* accounting.unformat("£ 12,345,678.90 GBP"); // 12345678.9
|
||
|
* ```
|
||
|
*
|
||
|
* @method unformat
|
||
|
* @for accounting
|
||
|
* @param {String|Array<String>} value The string or array of strings containing the number/s to parse.
|
||
|
* @param {Number} decimal Number of decimal digits of the resultant number
|
||
|
* @return {Float} The parsed number
|
||
|
*/
|
||
|
function unformat(value) {
|
||
|
var decimal = arguments.length <= 1 || arguments[1] === undefined ? settings.decimal : arguments[1];
|
||
|
var fallback = arguments.length <= 2 || arguments[2] === undefined ? settings.fallback : arguments[2];
|
||
|
|
||
|
// Recursively unformat arrays:
|
||
|
if (Array.isArray(value)) {
|
||
|
return value.map(function (val) {
|
||
|
return unformat(val, decimal, fallback);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Return the value as-is if it's already a number:
|
||
|
if (typeof value === 'number') return value;
|
||
|
|
||
|
// Build regex to strip out everything except digits, decimal point and minus sign:
|
||
|
var regex = new RegExp('[^0-9-(-)-' + decimal + ']', ['g']);
|
||
|
var unformattedValueString = ('' + value).replace(regex, '') // strip out any cruft
|
||
|
.replace(decimal, '.') // make sure decimal point is standard
|
||
|
.replace(/\(([-]*\d*[^)]?\d+)\)/g, '-$1') // replace bracketed values with negatives
|
||
|
.replace(/\((.*)\)/, ''); // remove any brackets that do not have numeric value
|
||
|
|
||
|
/**
|
||
|
* Handling -ve number and bracket, eg.
|
||
|
* (-100) = 100, -(100) = 100, --100 = 100
|
||
|
*/
|
||
|
var negative = (unformattedValueString.match(/-/g) || 2).length % 2,
|
||
|
absUnformatted = parseFloat(unformattedValueString.replace(/-/g, '')),
|
||
|
unformatted = absUnformatted * (negative ? -1 : 1);
|
||
|
|
||
|
// This will fail silently which may cause trouble, let's wait and see:
|
||
|
return !isNaN(unformatted) ? unformatted : fallback;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check and normalise the value of precision (must be positive integer)
|
||
|
*/
|
||
|
function _checkPrecision(val, base) {
|
||
|
val = Math.round(Math.abs(val));
|
||
|
return isNaN(val) ? base : val;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implementation of toFixed() that treats floats more like decimals
|
||
|
*
|
||
|
* Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present
|
||
|
* problems for accounting- and finance-related software.
|
||
|
*
|
||
|
* ```js
|
||
|
* (0.615).toFixed(2); // "0.61" (native toFixed has rounding issues)
|
||
|
* accounting.toFixed(0.615, 2); // "0.62"
|
||
|
* ```
|
||
|
*
|
||
|
* @method toFixed
|
||
|
* @for accounting
|
||
|
* @param {Float} value The float to be treated as a decimal number.
|
||
|
* @param {Number} [precision=2] The number of decimal digits to keep.
|
||
|
* @return {String} The given number transformed into a string with the given precission
|
||
|
*/
|
||
|
function toFixed(value, precision) {
|
||
|
precision = _checkPrecision(precision, settings.precision);
|
||
|
var power = Math.pow(10, precision);
|
||
|
|
||
|
// Multiply up by precision, round accurately, then divide and use native toFixed():
|
||
|
return (Math.round((value + 1e-8) * power) / power).toFixed(precision);
|
||
|
}
|
||
|
|
||
|
var index = __commonjs(function (module) {
|
||
|
/* eslint-disable no-unused-vars */
|
||
|
'use strict';
|
||
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
||
|
|
||
|
function toObject(val) {
|
||
|
if (val === null || val === undefined) {
|
||
|
throw new TypeError('Object.assign cannot be called with null or undefined');
|
||
|
}
|
||
|
|
||
|
return Object(val);
|
||
|
}
|
||
|
|
||
|
module.exports = Object.assign || function (target, source) {
|
||
|
var from;
|
||
|
var to = toObject(target);
|
||
|
var symbols;
|
||
|
|
||
|
for (var s = 1; s < arguments.length; s++) {
|
||
|
from = Object(arguments[s]);
|
||
|
|
||
|
for (var key in from) {
|
||
|
if (hasOwnProperty.call(from, key)) {
|
||
|
to[key] = from[key];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Object.getOwnPropertySymbols) {
|
||
|
symbols = Object.getOwnPropertySymbols(from);
|
||
|
for (var i = 0; i < symbols.length; i++) {
|
||
|
if (propIsEnumerable.call(from, symbols[i])) {
|
||
|
to[symbols[i]] = from[symbols[i]];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return to;
|
||
|
};
|
||
|
});
|
||
|
|
||
|
var objectAssign = (index && typeof index === 'object' && 'default' in index ? index['default'] : index);
|
||
|
|
||
|
function _stripInsignificantZeros(str, decimal) {
|
||
|
var parts = str.split(decimal);
|
||
|
var integerPart = parts[0];
|
||
|
var decimalPart = parts[1].replace(/0+$/, '');
|
||
|
|
||
|
if (decimalPart.length > 0) {
|
||
|
return integerPart + decimal + decimalPart;
|
||
|
}
|
||
|
|
||
|
return integerPart;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Format a number, with comma-separated thousands and custom precision/decimal places
|
||
|
* Alias: `accounting.format()`
|
||
|
*
|
||
|
* Localise by overriding the precision and thousand / decimal separators
|
||
|
*
|
||
|
* ```js
|
||
|
* accounting.formatNumber(5318008); // 5,318,008
|
||
|
* accounting.formatNumber(9876543.21, { precision: 3, thousand: " " }); // 9 876 543.210
|
||
|
* ```
|
||
|
*
|
||
|
* @method formatNumber
|
||
|
* @for accounting
|
||
|
* @param {Number} number The number to be formatted.
|
||
|
* @param {Object} [opts={}] Object containing all the options of the method.
|
||
|
* @return {String} The given number properly formatted.
|
||
|
*/
|
||
|
function formatNumber(number) {
|
||
|
var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
||
|
|
||
|
// Resursively format arrays:
|
||
|
if (Array.isArray(number)) {
|
||
|
return number.map(function (val) {
|
||
|
return formatNumber(val, opts);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Build options object from second param (if object) or all params, extending defaults:
|
||
|
opts = objectAssign({}, settings, opts);
|
||
|
|
||
|
// Do some calc:
|
||
|
var negative = number < 0 ? '-' : '';
|
||
|
var base = parseInt(toFixed(Math.abs(number), opts.precision), 10) + '';
|
||
|
var mod = base.length > 3 ? base.length % 3 : 0;
|
||
|
|
||
|
// Format the number:
|
||
|
var formatted = negative + (mod ? base.substr(0, mod) + opts.thousand : '') + base.substr(mod).replace(/(\d{3})(?=\d)/g, '$1' + opts.thousand) + (opts.precision > 0 ? opts.decimal + toFixed(Math.abs(number), opts.precision).split('.')[1] : '');
|
||
|
|
||
|
return opts.stripZeros ? _stripInsignificantZeros(formatted, opts.decimal) : formatted;
|
||
|
}
|
||
|
|
||
|
var index$1 = __commonjs(function (module) {
|
||
|
'use strict';
|
||
|
|
||
|
var strValue = String.prototype.valueOf;
|
||
|
var tryStringObject = function tryStringObject(value) {
|
||
|
try {
|
||
|
strValue.call(value);
|
||
|
return true;
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
var toStr = Object.prototype.toString;
|
||
|
var strClass = '[object String]';
|
||
|
var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
|
||
|
|
||
|
module.exports = function isString(value) {
|
||
|
if (typeof value === 'string') { return true; }
|
||
|
if (typeof value !== 'object') { return false; }
|
||
|
return hasToStringTag ? tryStringObject(value) : toStr.call(value) === strClass;
|
||
|
};
|
||
|
});
|
||
|
|
||
|
var isString = (index$1 && typeof index$1 === 'object' && 'default' in index$1 ? index$1['default'] : index$1);
|
||
|
|
||
|
/**
|
||
|
* Parses a format string or object and returns format obj for use in rendering
|
||
|
*
|
||
|
* `format` is either a string with the default (positive) format, or object
|
||
|
* containing `pos` (required), `neg` and `zero` values
|
||
|
*
|
||
|
* Either string or format.pos must contain "%v" (value) to be valid
|
||
|
*
|
||
|
* @method _checkCurrencyFormat
|
||
|
* @for accounting
|
||
|
* @param {String} [format="%s%v"] String with the format to apply, where %s is the currency symbol and %v is the value.
|
||
|
* @return {Object} object represnting format (with pos, neg and zero attributes)
|
||
|
*/
|
||
|
function _checkCurrencyFormat(format) {
|
||
|
// Format should be a string, in which case `value` ('%v') must be present:
|
||
|
if (isString(format) && format.match('%v')) {
|
||
|
// Create and return positive, negative and zero formats:
|
||
|
return {
|
||
|
pos: format,
|
||
|
neg: format.replace('-', '').replace('%v', '-%v'),
|
||
|
zero: format
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// Otherwise, assume format was fine:
|
||
|
return format;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Format a number into currency
|
||
|
*
|
||
|
* Usage: accounting.formatMoney(number, symbol, precision, thousandsSep, decimalSep, format)
|
||
|
* defaults: (0, '$', 2, ',', '.', '%s%v')
|
||
|
*
|
||
|
* Localise by overriding the symbol, precision, thousand / decimal separators and format
|
||
|
*
|
||
|
* ```js
|
||
|
* // Default usage:
|
||
|
* accounting.formatMoney(12345678); // $12,345,678.00
|
||
|
*
|
||
|
* // European formatting (custom symbol and separators), can also use options object as second parameter:
|
||
|
* accounting.formatMoney(4999.99, { symbol: "€", precision: 2, thousand: ".", decimal: "," }); // €4.999,99
|
||
|
*
|
||
|
* // Negative values can be formatted nicely:
|
||
|
* accounting.formatMoney(-500000, { symbol: "£ ", precision: 0 }); // £ -500,000
|
||
|
*
|
||
|
* // Simple `format` string allows control of symbol position (%v = value, %s = symbol):
|
||
|
* accounting.formatMoney(5318008, { symbol: "GBP", format: "%v %s" }); // 5,318,008.00 GBP
|
||
|
* ```
|
||
|
*
|
||
|
* @method formatMoney
|
||
|
* @for accounting
|
||
|
* @param {Number} number Number to be formatted.
|
||
|
* @param {Object} [opts={}] Object containing all the options of the method.
|
||
|
* @return {String} The given number properly formatted as money.
|
||
|
*/
|
||
|
function formatMoney(number) {
|
||
|
var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
||
|
|
||
|
// Resursively format arrays:
|
||
|
if (Array.isArray(number)) {
|
||
|
return number.map(function (val) {
|
||
|
return formatMoney(val, opts);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// Build options object from second param (if object) or all params, extending defaults:
|
||
|
opts = objectAssign({}, settings, opts);
|
||
|
|
||
|
// Check format (returns object with pos, neg and zero):
|
||
|
var formats = _checkCurrencyFormat(opts.format);
|
||
|
|
||
|
// Choose which format to use for this value:
|
||
|
var useFormat = undefined;
|
||
|
|
||
|
if (number > 0) {
|
||
|
useFormat = formats.pos;
|
||
|
} else if (number < 0) {
|
||
|
useFormat = formats.neg;
|
||
|
} else {
|
||
|
useFormat = formats.zero;
|
||
|
}
|
||
|
|
||
|
// Return with currency symbol added:
|
||
|
return useFormat.replace('%s', opts.symbol).replace('%v', formatNumber(Math.abs(number), opts));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Format a list of numbers into an accounting column, padding with whitespace
|
||
|
* to line up currency symbols, thousand separators and decimals places
|
||
|
*
|
||
|
* List should be an array of numbers
|
||
|
*
|
||
|
* Returns array of accouting-formatted number strings of same length
|
||
|
*
|
||
|
* NB: `white-space:pre` CSS rule is required on the list container to prevent
|
||
|
* browsers from collapsing the whitespace in the output strings.
|
||
|
*
|
||
|
* ```js
|
||
|
* accounting.formatColumn([123.5, 3456.49, 777888.99, 12345678, -5432], { symbol: "$ " });
|
||
|
* ```
|
||
|
*
|
||
|
* @method formatColumn
|
||
|
* @for accounting
|
||
|
* @param {Array<Number>} list An array of numbers to format
|
||
|
* @param {Object} [opts={}] Object containing all the options of the method.
|
||
|
* @param {Object|String} [symbol="$"] String with the currency symbol. For conveniency if can be an object containing all the options of the method.
|
||
|
* @param {Integer} [precision=2] Number of decimal digits
|
||
|
* @param {String} [thousand=','] String with the thousands separator.
|
||
|
* @param {String} [decimal="."] String with the decimal separator.
|
||
|
* @param {String} [format="%s%v"] String with the format to apply, where %s is the currency symbol and %v is the value.
|
||
|
* @return {Array<String>} array of accouting-formatted number strings of same length
|
||
|
*/
|
||
|
function formatColumn(list) {
|
||
|
var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
||
|
|
||
|
if (!list) return [];
|
||
|
|
||
|
// Build options object from second param (if object) or all params, extending defaults:
|
||
|
opts = objectAssign({}, settings, opts);
|
||
|
|
||
|
// Check format (returns object with pos, neg and zero), only need pos for now:
|
||
|
var formats = _checkCurrencyFormat(opts.format);
|
||
|
|
||
|
// Whether to pad at start of string or after currency symbol:
|
||
|
var padAfterSymbol = formats.pos.indexOf('%s') < formats.pos.indexOf('%v');
|
||
|
|
||
|
// Store value for the length of the longest string in the column:
|
||
|
var maxLength = 0;
|
||
|
|
||
|
// Format the list according to options, store the length of the longest string:
|
||
|
var formatted = list.map(function (val) {
|
||
|
if (Array.isArray(val)) {
|
||
|
// Recursively format columns if list is a multi-dimensional array:
|
||
|
return formatColumn(val, opts);
|
||
|
}
|
||
|
// Clean up the value
|
||
|
val = unformat(val, opts.decimal);
|
||
|
|
||
|
// Choose which format to use for this value (pos, neg or zero):
|
||
|
var useFormat = undefined;
|
||
|
|
||
|
if (val > 0) {
|
||
|
useFormat = formats.pos;
|
||
|
} else if (val < 0) {
|
||
|
useFormat = formats.neg;
|
||
|
} else {
|
||
|
useFormat = formats.zero;
|
||
|
}
|
||
|
|
||
|
// Format this value, push into formatted list and save the length:
|
||
|
var fVal = useFormat.replace('%s', opts.symbol).replace('%v', formatNumber(Math.abs(val), opts));
|
||
|
|
||
|
if (fVal.length > maxLength) {
|
||
|
maxLength = fVal.length;
|
||
|
}
|
||
|
|
||
|
return fVal;
|
||
|
});
|
||
|
|
||
|
// Pad each number in the list and send back the column of numbers:
|
||
|
return formatted.map(function (val) {
|
||
|
// Only if this is a string (not a nested array, which would have already been padded):
|
||
|
if (isString(val) && val.length < maxLength) {
|
||
|
// Depending on symbol position, pad after symbol or at index 0:
|
||
|
return padAfterSymbol ? val.replace(opts.symbol, opts.symbol + new Array(maxLength - val.length + 1).join(' ')) : new Array(maxLength - val.length + 1).join(' ') + val;
|
||
|
}
|
||
|
return val;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
export { settings, unformat, toFixed, formatMoney, formatNumber, formatColumn, formatMoney as format, unformat as parse };
|
||
|
//# sourceMappingURL=accounting.es6.js.map
|