UNPKG

@modelx/jsonm

Version:

Construct AI & ML models with JSON using Typescript & Tensorflow

152 lines (140 loc) 6.16 kB
import { Data, } from '@modelx/data/src/DataSet'; import { dimensionDates, } from './features'; import { Dimensions, } from './constants'; import { DataSets, } from './dataset'; // import Promisie from 'promisie'; import * as Luxon from 'luxon'; import { dataset0 } from './util'; // const _pipe = (a, b) => (arg) => b(a(arg)); // const pipe = (...ops) => ops.reduce(_pipe); export type CombineDatasetOptions = { datasets?: DataSets; field?: string; defaultObject?: any; includeEmptyDates?: boolean; dateFormat?: string; date_field?: string; time_zone?:string; dimension?:Dimensions; start_date?:string; end_date?:string; }; /** * Returns first dataset in datasets object passed to reducer functions * @example const datasets = { dataset_1:[{some:'data',}], dataset_2:[{some_two:'data',}], dataset_3:[{some_three:'data',}], } getFirstDataset(datasets) //=> [{some:'data',}] */ export function getFirstDataset(datasets:DataSets = {}):Data { return datasets[Object.keys(datasets)[0]] || []; } /** * sets a dates dataset based on a date range */ export function _helper_setEmptyDates({ dimension, start_date, end_date, time_zone, defaultObject, datasetsProperties, datasets, field, }: { dimension: Dimensions; start_date: string; end_date: string; time_zone: string; defaultObject?: any; datasetsProperties: string[]; datasets: DataSets; field: string; }){ const dates = dimensionDates[ dimension ]({ start: start_date, end: end_date, time_zone, }).map(date => { return Object.assign({}, defaultObject, { date, }); }); datasets = Object.keys(datasets).reduce((updatedDatasetData, datasetDataProperty) => { updatedDatasetData[ datasetDataProperty ] = datasets[ datasetDataProperty ].map(datum => { if (datum[field]) { const ISODateField = datum[ field ]; const updatedField = { [ field ]: Luxon.DateTime.fromISO(ISODateField, { zone: time_zone ||datum.time_zone, }).toJSDate(), }; // console.log(datum._id, 'datum[ field ]', datum[field], { ISODateField, datasetDataProperty, updatedField, datum }); return { ...datum, ...updatedField }; } else { return datum; } }); return updatedDatasetData; }, {}); // console.log('post dates', dates); datasets.dates = dates; datasetsProperties.splice(0, 0, 'dates'); return dates; } /** * Mutates combined dataset to formate date field based on Luxon dateFormat */ export function _helper_formatDateField({ combined, date_field, dateFormat }: { combined: Data; date_field: string; dateFormat: string;}) { const isJSDate = (combined[0][date_field] instanceof Date); for (let i = 0; i < combined.length; i++){ combined[i][date_field] = (isJSDate) ? Luxon.DateTime.fromJSDate(combined[i][date_field]).toFormat(dateFormat) : Luxon.DateTime.fromISO(combined[i][date_field]).toFormat(dateFormat); } } /** * Returns the first dataset that contains the field to combine on as the base dataset */ export function _helper_getBaseDataset({datasetsProperties, field, datasets}) { let baseDataset = []; let baseDatasetPropertyName; datasetsProperties.some((datasetsProperty) => { let datasetDatum = datasets[datasetsProperty]; if (datasetDatum.filter(dataSetDatumRow => typeof dataSetDatumRow[ field ] !== 'undefined').length) { baseDataset = datasetDatum; baseDatasetPropertyName = datasetsProperty; return datasetsProperty; } }); return { baseDataset, baseDatasetPropertyName, }; } export function combineDatasetsOnField({ datasets, field, defaultObject = {}, includeEmptyDates = false, dateFormat, date_field, time_zone, dimension, start_date, end_date, }:CombineDatasetOptions ={}) { if (!field) throw ReferenceError('In order to combine datasets, a field parameter is required'); // let datasets = datasets; const datasetsProperties = Object.keys(datasets); const { baseDataset, baseDatasetPropertyName, } = _helper_getBaseDataset({ datasetsProperties, field, datasets }); if (includeEmptyDates) { const dates = _helper_setEmptyDates({ dimension, start_date, end_date, time_zone, defaultObject, datasetsProperties, datasets, field, }); datasets.dates = dates; } let maxObjKeysLength = (baseDataset && baseDataset.length && typeof baseDataset[ 0 ] === 'object') ? Object.keys(baseDataset[ 0 ]).length : 0; let maxObjKeysLengthIndex = 0; const combined = baseDataset.reduce((combinedDataset, row, rowIndex) => { let combinedRow = { ...defaultObject, ...row, }; datasetsProperties.filter(datasetsPropertyName => datasetsPropertyName !== baseDatasetPropertyName).forEach(datasetsPropertyName => { const matchingRow = datasets[ datasetsPropertyName ].find(dsRow => { return (dsRow[field] === row[field] || (dsRow[field] && row[field] && dsRow[field].toString() === row[field].toString())); }); if (matchingRow) { Object.keys(matchingRow).reduce((result, key) => { if (typeof matchingRow[key] !== 'undefined') { result[key] = matchingRow[key]; } return result; }, combinedRow); // Object.assign(combinedRow,matchingRow) } }); if (Object.keys(combinedRow).length > maxObjKeysLength) { maxObjKeysLength = Object.keys(combinedRow).length; maxObjKeysLengthIndex = rowIndex; } combinedDataset.push(combinedRow); return combinedDataset; }, []); // console.log('combined',combined); if (maxObjKeysLengthIndex !== 0) {//fix first data row to have all data properties for table display const emtpyObject = Object.keys(combined[ maxObjKeysLengthIndex ]).reduce((blankObj, prop) => { blankObj[ prop ] = undefined; return blankObj; }, {}); combined[ 0 ] = Object.assign({}, emtpyObject, combined[ 0 ]); } if (date_field && dateFormat) _helper_formatDateField({ combined, date_field, dateFormat }); return combined; }