one-hot-json
Version:
flattening JSON Objects and encoding values via one-hot approach
117 lines (97 loc) • 2.5 kB
JavaScript
;
const _ = require('lodash');
const pathfinder = require('json-pathfinder');
const shape = {
array: require('shape-array')
};
const OneHotString = (values) => {
let uniques = _.uniq(values);
let encode = (value) => {
if(_.indexOf(uniques, value) === -1) {
uniques.push(value);
}
return _.findIndex(uniques, str => str === value);
};
let decode = (number) => {
return uniques[_.round(number)];
};
return {
encode: encode,
decode: decode
};
};
const OneHotNumber = (values) => {
let type = 'integer';
let encode = (value) => {
if(_.isInteger(value) === false) {
type = 'float';
}
return value;
};
let decode = (value) => {
if(type === 'integer') {
return _.round(value);
}
return value;
};
return {
encode: encode,
decode: decode
};
};
const getType = (path, json) => {
let value = _.get(json, path);
if(_.isString(value)) return 'string';
if(_.isBoolean(value)) return 'boolean';
if(_.isNumber(value)) return 'number';
};
const onehot = (reference) => {
let paths = pathfinder.parse(reference);
let patterns = _.map(paths, (path, index) => {
let pattern = {
path: path,
type: getType(path, reference)
};
if(pattern.type === 'string') {
pattern.onehot = OneHotString([_.get(reference, path)]);
}
if(pattern.type === 'boolean') {
pattern.onehot = OneHotString(['false', 'true']);
}
if(pattern.type === 'number') {
pattern.onehot = OneHotNumber([_.get(reference, path)]);
}
return pattern;
});
let flatten = shape.array.reverse(paths);
let encode = (collection) => {
if(_.isArray(collection) === false) collection = [collection];
return _.map(collection, item => {
let row = flatten(item);
return _.map(patterns, (pattern, index) => {
if(pattern.onehot) {
return pattern.onehot.encode(row[index]);
}
return row[index];
});
});
};
let deflatten = shape.array.scheme(paths);
let decode = (collection) => {
if(_.isArray(collection) === false) collection = [collection];
return _.map(collection, row => {
return deflatten(_.map(patterns, (pattern, index) => {
let value = row[index];
if(pattern.onehot) {
value = pattern.onehot.decode(value);
}
return value;
}));
});
};
return {
encode: encode,
decode: decode
};
};
module.exports = onehot;