Skip to content
This repository has been archived by the owner on May 2, 2022. It is now read-only.

Commit

Permalink
Merge branch 'release/v2.2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
rousan committed May 3, 2019
2 parents f4020d1 + 3911707 commit cb2c3df
Show file tree
Hide file tree
Showing 10 changed files with 606 additions and 116 deletions.
2 changes: 1 addition & 1 deletion dist/datamodel.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/datamodel.js.map

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
</head>

<body>
<!-- <script src="./samples/example5.js"></script> -->
<script src="./samples/example4.js"></script>
<script src="./samples/sample-with-split.js"></script>
<!-- <script src="./samples/example3.js"></script> -->
</body>

Expand Down
66 changes: 66 additions & 0 deletions example/samples/sample-with-split.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable */

const DataModel = window.DataModel;
let dm;

d3.json('./data/cars.json', (data) => {
const jsonData = data,
schema = [{
name: 'Name',
type: 'dimension'
}, {
name: 'Miles_per_Gallon',
type: 'measure',
unit : 'cm',
scale: '1000',
numberformat: '12-3-3'
}, {
name: 'Cylinders',
type: 'dimension'
}, {
name: 'Displacement',
type: 'measure'
}, {
name: 'Horsepower',
type: 'measure'
}, {
name: 'Weight_in_lbs',
type: 'measure',
}, {
name: 'Acceleration',
type: 'measure'
}, {
name: 'Year',
type: 'dimension',
subtype: 'temporal',
format: '%Y-%m-%d'

}, {
name: 'Origin',
type: 'dimension'
}];
window.datamodel = new DataModel(jsonData, schema);

const splitDms = datamodel.splitByRow(['Year']);
console.log(splitDms);


const splitDmsMultipleDimensions = datamodel.splitByRow(['Year', 'Cylinders']);
console.log(splitDmsMultipleDimensions);

const dmWithCondition = datamodel.splitByRow(['Origin', 'Cylinders'], (fields)=>fields.Cylinders.value !== '6');
console.log(dmWithCondition);

const dmWithConditionInverse = datamodel.splitByRow(['Origin', 'Cylinders'], (fields)=>fields.Cylinders.value !== '6', {mode: undefined});
console.log(dmWithConditionInverse);
const dmWithConditionInverse2 = datamodel.select( (fields)=>fields.Cylinders.value !== '6', {mode: undefined});
console.log(dmWithConditionInverse2);

const projectDm = datamodel.splitByColumn([['Acceleration'], ['Horsepower']], ['Origin']);
console.log(projectDm);


const compose = window.DataModel.Operators.compose;
const splitByRow = window.DataModel.Operators.splitByRow;

});
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "datamodel",
"description": "Relational algebra compliant in-memory tabular data store",
"homepage": "https://github.com/chartshq/datamodel",
"version": "2.2.0",
"version": "2.2.1",
"license": "MIT",
"main": "dist/datamodel.js",
"keywords": [
Expand Down Expand Up @@ -81,7 +81,9 @@
"test": "npm run lint && npm run ut",
"ut": "karma start karma.conf.js",
"utd": "karma start --single-run false --browsers Chrome karma.conf.js ",
"build": "webpack --mode production",
"build": "npm run build:prod",
"build:dev": "webpack --mode development",
"build:prod": "webpack --mode production",
"start": "webpack-dev-server --config webpack.config.dev.js --mode development --open",
"lint": "eslint ./src",
"lint-errors": "eslint --quiet ./src",
Expand Down
156 changes: 154 additions & 2 deletions src/datamodel.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/* eslint-disable default-case */

import { FieldType, DimensionSubtype, DataFormat } from './enums';
import { FieldType, DimensionSubtype, DataFormat, FilteringMode } from './enums';
import {
persistDerivations,
getRootGroupByModel,
propagateToAllDataModels,
getRootDataModel,
propagateImmutableActions,
addToPropNamespace,
sanitizeUnitSchema
sanitizeUnitSchema,
splitWithSelect,
splitWithProject,
getNormalizedProFields
} from './helper';
import { DM_DERIVATIVES, PROPAGATION } from './constants';
import {
Expand All @@ -21,6 +24,7 @@ import Relation from './relation';
import reducerStore from './utils/reducer-store';
import { createFields } from './field-creator';
import InvalidAwareTypes from './invalid-aware-types';
import Value from './value';

/**
* DataModel is an in-browser representation of tabular data. It supports
Expand Down Expand Up @@ -209,6 +213,28 @@ class DataModel extends Relation {
return dataGenerated;
}

/**
* Returns the unique ids in an array.
*
* @return {Array} Returns an array of ids.
*/
getUids () {
const rowDiffset = this._rowDiffset;
const ids = [];

if (rowDiffset.length) {
const diffSets = rowDiffset.split(',');

diffSets.forEach((set) => {
let [start, end] = set.split('-').map(Number);

end = end !== undefined ? end : start;
ids.push(...Array(end - start + 1).fill().map((_, idx) => start + idx));
});
}

return ids;
}
/**
* Groups the data using particular dimensions and by reducing measures. It expects a list of dimensions using which
* it projects the datamodel and perform aggregations to reduce the duplicate tuples. Refer this
Expand Down Expand Up @@ -404,9 +430,13 @@ class DataModel extends Relation {
const fieldName = field.name();
this._colIdentifier += `,${fieldName}`;
const partialFieldspace = this._partialFieldspace;
const cachedValueObjects = partialFieldspace._cachedValueObjects;

if (!partialFieldspace.fieldsObj()[field.name()]) {
partialFieldspace.fields.push(field);
cachedValueObjects.forEach((obj, i) => {
obj[field.name()] = new Value(field.partialField.data[i], field);
});
} else {
const fieldIndex = partialFieldspace.fields.findIndex(fieldinst => fieldinst.name() === fieldName);
fieldIndex >= 0 && (partialFieldspace.fields[fieldIndex] = field);
Expand Down Expand Up @@ -695,6 +725,128 @@ class DataModel extends Relation {

return new DataModel(data, schema);
}

/**
* Creates a set of new {@link DataModel} instances by splitting the set of rows in the source {@link DataModel}
* instance based on a set of dimensions.
*
* For each unique dimensional value, a new split is created which creates a unique {@link DataModel} instance for
* that split
*
* If multiple dimensions are provided, it splits the source {@link DataModel} instance with all possible
* combinations of the dimensional values for all the dimensions provided
*
* Additionally, it also accepts a predicate function to reduce the set of rows provided. A
* {@link link_to_selection | Selection} is performed on all the split {@link DataModel} instances based on
* the predicate function
*
* @example
* // without predicate function:
* const splitDt = dt.splitByRow(['Origin'])
* console.log(splitDt));
* // This should give three unique DataModel instances, one each having rows only for 'USA',
* // 'Europe' and 'Japan' respectively
*
* @example
* // without predicate function:
* const splitDtMulti = dt.splitByRow(['Origin', 'Cylinders'])
* console.log(splitDtMulti));
* // This should give DataModel instances for all unique combinations of Origin and Cylinder values
*
* @example
* // with predicate function:
* const splitWithPredDt = dt.select(['Origin'], fields => fields.Origin.value === "USA")
* console.log(splitWithPredDt);
* // This should not include the DataModel for the Origin : 'USA'
*
*
* @public
*
* @param {Array} dimensionArr - Set of dimensions based on which the split should occur
* @param {Object} config - The configuration object
* @param {string} [config.saveChild] - Configuration to save child or not
* @param {string}[config.mode=FilteringMode.NORMAL] -The mode of the selection.
* @return {Array} Returns the new DataModel instances after operation.
*/
splitByRow (dimensionArr, reducerFn, config) {
const fieldsConfig = this.getFieldsConfig();

dimensionArr.forEach((fieldName) => {
if (!fieldsConfig[fieldName]) {
throw new Error(`Field ${fieldName} doesn't exist in the schema`);
}
});

const defConfig = {
mode: FilteringMode.NORMAL,
saveChild: true
};

config = Object.assign({}, defConfig, config);

return splitWithSelect(this, dimensionArr, reducerFn, config);
}

/**
* Creates a set of new {@link DataModel} instances by splitting the set of fields in the source {@link DataModel}
* instance based on a set of common and unique field names provided.
*
* Each DataModel created contains a set of fields which are common to all and a set of unique fields.
* It also accepts configurations such as saveChild and mode(inverse or normal) to include/exclude the respective
* fields
*
* @example
* // without predicate function:
* const splitDt = dt.splitByColumn( [['Acceleration'], ['Horsepower']], ['Origin'])
* console.log(splitDt));
* // This should give two unique DataModel instances, both having the field 'Origin' and
* // one each having 'Acceleration' and 'Horsepower' fields respectively
*
* @example
* // without predicate function:
* const splitDtInv = dt.splitByColumn( [['Acceleration'], ['Horsepower'],['Origin', 'Cylinders'],
* {mode: 'inverse'})
* console.log(splitDtInv));
* // This should give DataModel instances in the following way:
* // All DataModel Instances do not have the fields 'Origin' and 'Cylinders'
* // One DataModel Instance has rest of the fields except 'Acceleration' and the other DataModel instance
* // has rest of the fields except 'Horsepower'
*
*
*
* @public
*
* @param {Array} uniqueFields - Set of unique fields included in each datamModel instance
* @param {Array} commonFields - Set of common fields included in all datamModel instances
* @param {Object} config - The configuration object
* @param {string} [config.saveChild] - Configuration to save child or not
* @param {string}[config.mode=FilteringMode.NORMAL] -The mode of the selection.
* @return {Array} Returns the new DataModel instances after operation.
*/
splitByColumn (uniqueFields = [], commonFields = [], config) {
const defConfig = {
mode: FilteringMode.NORMAL,
saveChild: true
};
const fieldConfig = this.getFieldsConfig();
const allFields = Object.keys(fieldConfig);
const normalizedProjFieldSets = [[commonFields]];

config = Object.assign({}, defConfig, config);
uniqueFields = uniqueFields.length ? uniqueFields : [[]];


uniqueFields.forEach((fieldSet, i) => {
normalizedProjFieldSets[i] = getNormalizedProFields(
[...fieldSet, ...commonFields],
allFields,
fieldConfig);
});

return splitWithProject(this, normalizedProjFieldSets, config, allFields);
}


}

export default DataModel;
Loading

0 comments on commit cb2c3df

Please sign in to comment.