GithubHelp home page GithubHelp logo

pat310 / quick-pivot Goto Github PK

View Code? Open in Web Editor NEW
62.0 8.0 21.0 434 KB

Quickly format data to create a pivot table

Home Page: https://www.npmjs.com/package/quick-pivot

License: MIT License

JavaScript 100.00%
pivot pivot-tables javascript

quick-pivot's Introduction

NPM

npm version Build Status Coverage Status Code Climate Dependency Status

What it does

Say you have this example data set:
example data

With this tool you can pivot the data given a particular row and column category:
example pivot 1

Or given multiple rows and a column category:
example pivot 2

Or multiple columns and a row category:
example pivot 3

Or any combination of rows and/or columns

Example use

Install with npm: npm install --save quick-pivot

import Pivot from 'quick-pivot';

const dataArray = [
 ['name', 'gender', 'house', 'age'],
 ['Jon', 'm', 'Stark', 14],
 ['Arya', 'f', 'Stark', 10],
 ['Cersei', 'f', 'Baratheon', 38],
 ['Tywin', 'm', 'Lannister', 67],
 ['Tyrion', 'm', 'Lannister', 34],
 ['Joffrey', 'm', 'Baratheon', 18],
 ['Bran', 'm', 'Stark', 8],
 ['Jaime', 'm', 'Lannister', 32],
 ['Sansa', 'f', 'Stark', 12]
];

const rowsToPivot = ['name'];
const colsToPivot = ['house', 'gender'];
const aggregationDimension = 'age';
const aggregator = 'sum';

const pivot = new Pivot(dataArray, rowsToPivot, colsToPivot, aggregationDimension, aggregator);

console.log('pivot.data', pivot.data, 'pivot.data.table', pivot.data.table);

console logs:

pivot.data
{ table:
   [ { value: [Object], depth: 0, type: 'colHeader', row: 0 },
     { value: [Object], depth: 1, type: 'colHeader', row: 1 },
     { value: [Object], type: 'data', depth: 0, row: 2 },
     { value: [Object], type: 'data', depth: 0, row: 3 },
     { value: [Object], type: 'data', depth: 0, row: 4 },
     { value: [Object], type: 'data', depth: 0, row: 5 },
     { value: [Object], type: 'data', depth: 0, row: 6 },
     { value: [Object], type: 'data', depth: 0, row: 7 },
     { value: [Object], type: 'data', depth: 0, row: 8 },
     { value: [Object], type: 'data', depth: 0, row: 9 },
     { value: [Object], type: 'data', depth: 0, row: 10 },
     { value: [Object], type: 'aggregated' } ],
  rawData:
   [ { value: [Object], depth: 0, type: 'colHeader', row: 0 },
     { value: [Object], depth: 1, type: 'colHeader', row: 1 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 },
     { value: [Object], type: 'data', depth: 0 } ] }

pivot.data.table
[ { value:
     [ 'sum age',
       'Stark',
       'Stark',
       'Baratheon',
       'Baratheon',
       'Lannister',
       'Totals' ],
    depth: 0,
    type: 'colHeader',
    row: 0 },
  { value: [ 'sum age', 'f', 'm', 'f', 'm', 'm', '' ],
    depth: 1,
    type: 'colHeader',
    row: 1 },
  { value: [ 'Arya', 10, '', '', '', '', 10 ],
    type: 'data',
    depth: 0,
    row: 2 },
  { value: [ 'Bran', '', 8, '', '', '', 8 ],
    type: 'data',
    depth: 0,
    row: 3 },
  { value: [ 'Cersei', '', '', 38, '', '', 38 ],
    type: 'data',
    depth: 0,
    row: 4 },
  { value: [ 'Jaime', '', '', '', '', 32, 32 ],
    type: 'data',
    depth: 0,
    row: 5 },
  { value: [ 'Joffrey', '', '', '', 18, '', 18 ],
    type: 'data',
    depth: 0,
    row: 6 },
  { value: [ 'Jon', '', 14, '', '', '', 14 ],
    type: 'data',
    depth: 0,
    row: 7 },
  { value: [ 'Sansa', 12, '', '', '', '', 12 ],
    type: 'data',
    depth: 0,
    row: 8 },
  { value: [ 'Tyrion', '', '', '', '', 34, 34 ],
    type: 'data',
    depth: 0,
    row: 9 },
  { value: [ 'Tywin', '', '', '', '', 67, 67 ],
    type: 'data',
    depth: 0,
    row: 10 },
  { value: [ 'Totals', 22, 22, 38, 18, 133, '' ], type: 'aggregated' } ]

API

Pivot data value

The data value returns an object with keys table and rawData. table is an array of objects with each object containing four keys (except for the last object which is an aggregated row of all the previous data rows based on the selected aggregation function):

  1. value - Array which contains the result of the pivot to be rendered
  2. type - Enumerated string describing what this data row contains, [data, rowHeader, or colHeader]
  3. depth - Number describing how deeply nested the row is within a parent row
  4. row - Number describing the original row index within the table

rawData is an array of objects with three keys:

  1. value - Array which contains the data that makes up that particular row
  2. type - Enumerated string describing what this data row contains, [data, rowHeader, or colHeader]
  3. depth - Number describing how deeply nested the row is within a parent row

Syntax

Note: If modules are not supported in your environment, you can also require var Pivot = require('quick-pivot');

import Pivot from 'quick-pivot';

const pivot = new Pivot(dataArray, rows, columns, [aggregationDimension or CBfunction], [aggregator or initialValue], rowHeader, sortFunction, columnSortFunction);

First way to use it:

  • dataArray required is one of the following:
    • array of arrays ( the array in first index is assumed to be your headers, see the example above)
    • array of objects (the keys of each object are the headers)
    • a single array (a single column of data where the first element is the header)
  • rows is an array of strings (the rows you want to pivot on) or an empty array required
  • columns is an array of strings (the columns you want to pivot on) or an empty array required
  • aggregationDimension is a string (the category you want to accumulate values for) required
  • aggregator is an enumerated string - either 'sum', 'count', 'min', 'max', or 'average' (the type of accumulation you want to perform). If no type is selected, 'count' is chosen by default
  • rowHeader is a string (this value will appear above the rows)
  • sortFunction is a custom sorting function for rows. Default sorting used if null
    • Sort Function should be in the form (row) => (a,b) => Number. This Function will be called for each row pivoted on (right to left) and must return a traditional Array.sort function as a result. A Function equaling () => {} will direct the Pivot to skip the sorting phase.
  • columnSortFunction is a custom sorting function for columns. No sorting used if undefined
    • Column Sort Function should be in the form (data, columns, columnIndex) => (a,b) => Number. This Function will be called for each column pivoted on and must return a traditional Array.sort function as a result.

Second way to use it:

Parameters are the same as the first except for two, aggregationDimension and aggregator. Instead of aggregationDimension and aggregator, you can use the following:

  • CBfunction is a callback function that receives four parameters CBfunction(acc, curr, index, arr) where acc is an accumulation value, curr is the current element being processed, index is the index of the current element being processed and arr is the array that is being acted on. This function must return the accumulation value (this is very similar to javascript's .reduce) required
  • initialValue is the starting value for the callback function. If no starting value is selected, 0 is used by default.

Methods/Instance Variables

.data

Instance variable that returns the data array shown above

.update(dataArray, rows, columns, [aggregationDimension or CBfunction], [aggregator or initialValue], rowHeader)

Updates the .data instance variable. The update method is chainable.

.collapse(rowNum)

Collapses data into the specified row header provided. rowNum is the row header's current index within the table (Not the original row index that is provided in the object). The collapse method is chainable

.expand(rowNum)

Expands collapsed data that has previously been collapsed. The expand method is chainable.

.collapseAll()

Collapses all data. The collapseAll method is chainable.

.expandAll()

Expands all data. The expandAll method is chainable.

.toggle(rowNum)

Toggles data from collapsed to expanded or vice-versa. The toggle method is chainable.

.getData(rowNum)

Returns the data that comprises a collapsed row

.getUniqueValues(fieldName)

Returns all the unique values for a particular field as an array

.filter([fieldName or CBfunction], filterValues, [filterType])

Filters out values based on either:

  • string fieldName field to filter on, array filterValues values to filter, string filterType optional enumerated string either 'include' or 'exclude' (defaults to exclude if not provided)
  • function CBfunction(element, index, array) which iterates over each element in array (similar to Javascript array .filter method)

Example with callback function

Check out the test spec for more examples.

import Pivot from 'quick-pivot';

function cbFunc(acc, curr, index, arr){
  acc += curr.age;
  if(index === arr.length - 1) return acc / arr.length;
  return acc;
}
const pivot = new Pivot(dataArray, ['gender'], ['house'], cbFunc, 0, 'average age');

console.log(pivot.data.table);
/*
[ { value: [ 'average age', 'Stark', 'Baratheon', 'Lannister', 'Totals' ],
    depth: 0,
    type: 'colHeader',
    row: 0 },
  { value: [ 'f', 11, 38, '', 20 ], type: 'data', depth: 0, row: 1 },
  { value: [ 'm', 11, 18, 44.333333333333336, 28.833333333333332 ],
    type: 'data',
    depth: 0,
    row: 2 },
  { value: [ 'Totals', 11, 28, 44.333333333333336, '' ],
    type: 'aggregated' } ]
*/

pivot.update(dataArray, ['gender', 'name'], ['house'], cbFunc, 0, 'average age')

console.log(pivot.data.table);
/*
[ { value: [ 'average age', 'Stark', 'Baratheon', 'Lannister', 'Totals' ],
    depth: 0,
    type: 'colHeader',
    row: 0 },
  { value: [ 'f', 11, 38, '', '' ],
    depth: 0,
    type: 'rowHeader',
    row: 1 },
  { value: [ 'Arya', 10, '', '', 10 ],
    type: 'data',
    depth: 1,
    row: 2 },
  { value: [ 'Cersei', '', 38, '', 38 ],
    type: 'data',
    depth: 1,
    row: 3 },
  { value: [ 'Sansa', 12, '', '', 12 ],
    type: 'data',
    depth: 1,
    row: 4 },
  { value: [ 'm', 11, 18, 44.333333333333336, '' ],
    depth: 0,
    type: 'rowHeader',
    row: 5 },
  { value: [ 'Bran', 8, '', '', 8 ],
    type: 'data',
    depth: 1,
    row: 6 },
  { value: [ 'Jaime', '', '', 32, 32 ],
    type: 'data',
    depth: 1,
    row: 7 },
  { value: [ 'Joffrey', '', 18, '', 18 ],
    type: 'data',
    depth: 1,
    row: 8 },
  { value: [ 'Jon', 14, '', '', 14 ],
    type: 'data',
    depth: 1,
    row: 9 },
  { value: [ 'Tyrion', '', '', 34, 34 ],
    type: 'data',
    depth: 1,
    row: 10 },
  { value: [ 'Tywin', '', '', 67, 67 ],
    type: 'data',
    depth: 1,
    row: 11 },
  { value: [ 'Totals', 11, 28, 44.333333333333336, '' ],
    type: 'aggregated' } ]
*/

pivot.collapse(1);

console.log(pivot.data.table);
/*
[ { value: [ 'average age', 'Stark', 'Baratheon', 'Lannister', 'Totals' ],
    depth: 0,
    type: 'colHeader',
    row: 0 },
  { value: [ 'f', 11, 38, '', '' ],
    depth: 0,
    type: 'rowHeader',
    row: 1 },
  { value: [ 'm', 11, 18, 44.333333333333336, '' ],
    depth: 0,
    type: 'rowHeader',
    row: 5 },
  { value: [ 'Bran', 8, '', '', 8 ],
    type: 'data',
    depth: 1,
    row: 6 },
  { value: [ 'Jaime', '', '', 32, 32 ],
    type: 'data',
    depth: 1,
    row: 7 },
  { value: [ 'Joffrey', '', 18, '', 18 ],
    type: 'data',
    depth: 1,
    row: 8 },
  { value: [ 'Jon', 14, '', '', 14 ],
    type: 'data',
    depth: 1,
    row: 9 },
  { value: [ 'Tyrion', '', '', 34, 34 ],
    type: 'data',
    depth: 1,
    row: 10 },
  { value: [ 'Tywin', '', '', 67, 67 ],
    type: 'data',
    depth: 1,
    row: 11 },
  { value: [ 'Totals', 11, 28, 44.333333333333336, '' ],
    type: 'aggregated' } ]
*/

console.log(pivot.getData(1));
/*
[ { value: [ 'Arya', [Array], '', '' ], type: 'data', depth: 1 },
  { value: [ 'Cersei', '', [Array], '' ], type: 'data', depth: 1 },
  { value: [ 'Sansa', [Array], '', '' ], type: 'data', depth: 1 } ]
*/

console.log(pivot.getData(1)[0].value)
/*
[ 'Arya',
  [ { name: 'Arya', gender: 'f', house: 'Stark', age: 10 } ],
  '',
  '' ]
*/

pivot.collapse(2);

console.log(pivot.data.table);
/*
[ { value: [ 'average age', 'Stark', 'Baratheon', 'Lannister', 'Totals' ],
    depth: 0,
    type: 'colHeader',
    row: 0 },
  { value: [ 'f', 11, 38, '', '' ],
    depth: 0,
    type: 'rowHeader',
    row: 1 },
  { value: [ 'm', 11, 18, 44.333333333333336, '' ],
    depth: 0,
    type: 'rowHeader',
    row: 5 },
  { value: [ 'Totals', 11, 28, 44.333333333333336, '' ],
    type: 'aggregated' } ]
*/

pivot.expand(1);
console.log(pivot.data.table);
/*
[ { value: [ 'average age', 'Stark', 'Baratheon', 'Lannister', 'Totals' ],
    depth: 0,
    type: 'colHeader',
    row: 0 },
  { value: [ 'f', 11, 38, '', '' ],
    depth: 0,
    type: 'rowHeader',
    row: 1 },
  { value: [ 'Arya', 10, '', '', 10 ],
    type: 'data',
    depth: 1,
    row: 2 },
  { value: [ 'Cersei', '', 38, '', 38 ],
    type: 'data',
    depth: 1,
    row: 3 },
  { value: [ 'Sansa', 12, '', '', 12 ],
    type: 'data',
    depth: 1,
    row: 4 },
  { value: [ 'm', 11, 18, 44.333333333333336, '' ],
    depth: 0,
    type: 'rowHeader',
    row: 5 },
  { value: [ 'Totals', 11, 28, 44.333333333333336, '' ],
    type: 'aggregated' } ]

Changes

Check out the change log

quick-pivot's People

Contributors

astrada-sieds avatar corvana-nbaker avatar jedrus2000 avatar pat310 avatar tommuijsers-ee avatar turnerniles avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quick-pivot's Issues

Create excel sheet from the pivot data

How I can create an excel sheet from 'pivot' variable

const pivot = new Pivot(array, ['Region'], ['ActiveCustomers','ActiveUsers'], 'viewaccess', 'sum').collapseAll();

my data looks like

[ { value: [ 'sum viewaccess', '2', 'Totals' ], depth: 0, type: 'colHeader', row: 0 }, { value: [ 'sum viewaccess', '1', '' ], depth: 1, type: 'colHeader', row: 1 }, { value: [ 'North West', 0, 0 ], type: 'data', depth: 0, row: 2 }, { value: [ 'Totals', 0, '' ], type: 'aggregated' } ]

Bizarre aggregation results when column/row fields are provided in certain orders

Quick-pivot is aggregating bizarrely when provided with rows/columns in certain orders. Occurs when providing various combinations of rows and columns. Not specific to the rows and no columns aggregation example below.

const workingPivot = new Pivot([['name', 'gender', 'house', 'age'],['Jon', 'm', 'Stark', 14],['Arya', 'f', 'Stark', 10],['Cersei', 'f', 'Baratheon', 38],['Tywin', 'm', 'Lannister', 67],['Tyrion', 'm', 'Lannister', 34],['Joffrey', 'm', 'Baratheon', 18],['Bran', 'm', 'Stark', 8],['Jaime', 'm', 'Lannister', 32],['Sansa', 'f', 'Stark', 12]],['gender','house'],[], '', 'count')

image

const bugPivot = new Pivot([['name', 'gender', 'house', 'age'],['Jon', 'm', 'Stark', 14],['Arya', 'f', 'Stark', 10],['Cersei', 'f', 'Baratheon', 38],['Tywin', 'm', 'Lannister', 67],['Tyrion', 'm', 'Lannister', 34],['Joffrey', 'm', 'Baratheon', 18],['Bran', 'm', 'Stark', 8],['Jaime', 'm', 'Lannister', 32],['Sansa', 'f', 'Stark', 12]],['house','gender'],[], '', 'count')

image

const bugPivot2 = new Pivot([['name', 'gender', 'house', 'age'],['Jon', 'm', 'Stark', 14],['Arya', 'f', 'Stark', 10],['Cersei', 'f', 'Baratheon', 38],['Tywin', 'm', 'Lannister', 67],['Tyrion', 'm', 'Lannister', 34],['Joffrey', 'm', 'Baratheon', 18],['Bran', 'm', 'Stark', 8],['Jaime', 'm', 'Lannister', 32],['Sansa', 'f', 'Stark', 12]],[],['house','gender'], '', 'count')

image

Grouping order changes upon filtering of sub-grouping

When you filter on certain sub groupings the main grouping order changes and get moved to the bottom.

const dataArray = [['name', 'gender', 'house', 'age'],['Jon', 'm', 'Stark', 14],['Arya', 'f', 'Stark', 10],['Cersei', 'f', 'Baratheon', 38],['Tywin', 'm', 'Lannister', 67],['Tyrion', 'm', 'Lannister', 34],['Joffrey', 'm', 'Baratheon', 18],['Bran', 'm', 'Stark', 8],['Jaime', 'm', 'Lannister', 32],['Sansa', 'f', 'Stark', 12]
];

const testPivot = new pivot(dataArray, ['gender', 'house'], [], 'age', 'sum');

Result of JSON.stringify(testPivot.data.table):
"[{"value":["sum age","sum age"],"depth":0,"type":"colHeader","row":0},{"value":["m",173],"depth":0,"type":"rowHeader","row":1},{"value":["Stark",22],"type":"data","depth":1,"row":2},{"value":["Lannister",133],"type":"data","depth":1,"row":3},{"value":["Baratheon",18],"type":"data","depth":1,"row":4},{"value":["f",60],"depth":0,"type":"rowHeader","row":5},{"value":["Stark",22],"type":"data","depth":1,"row":6},{"value":["Baratheon",38],"type":"data","depth":1,"row":7}]"

testPivot.filter('house', ['Stark'])

Result of JSON.stringify(testPivot.data.table):
"[{"value":["sum age","sum age"],"depth":0,"type":"colHeader","row":0},{"value":["f",38],"depth":0,"type":"rowHeader","row":1},{"value":["Baratheon",38],"type":"data","depth":1,"row":2},{"value":["m",151],"depth":0,"type":"rowHeader","row":3},{"value":["Lannister",133],"type":"data","depth":1,"row":4},{"value":["Baratheon",18],"type":"data","depth":1,"row":5}]"

Notice how the 'm' grouping is shifted to the second position. However, filtering on Baratheon does not cause the shift in order. It's unclear to me what exact scenarios cause the shift.

const dataArray = [['name', 'gender', 'house', 'age'],['Jon', 'm', 'Stark', 14],['Arya', 'f', 'Stark', 10],['Cersei', 'f', 'Baratheon', 38],['Tywin', 'm', 'Lannister', 67],['Tyrion', 'm', 'Lannister', 34],['Joffrey', 'm', 'Baratheon', 18],['Bran', 'm', 'Stark', 8],['Jaime', 'm', 'Lannister', 32],['Sansa', 'f', 'Stark', 12]
];

const testPivot = new pivot(dataArray, ['gender', 'house'], [], 'age', 'sum');

Result of JSON.stringify(testPivot.data.table):
"[{"value":["sum age","sum age"],"depth":0,"type":"colHeader","row":0},{"value":["m",173],"depth":0,"type":"rowHeader","row":1},{"value":["Stark",22],"type":"data","depth":1,"row":2},{"value":["Lannister",133],"type":"data","depth":1,"row":3},{"value":["Baratheon",18],"type":"data","depth":1,"row":4},{"value":["f",60],"depth":0,"type":"rowHeader","row":5},{"value":["Stark",22],"type":"data","depth":1,"row":6},{"value":["Baratheon",38],"type":"data","depth":1,"row":7}]"

testPivot.filter('house', ['Baratheon'])

Result of JSON.stringify(testPivot.data.table):
"[{"value":["sum age","sum age"],"depth":0,"type":"colHeader","row":0},{"value":["m",155],"depth":0,"type":"rowHeader","row":1},{"value":["Stark",22],"type":"data","depth":1,"row":2},{"value":["Lannister",133],"type":"data","depth":1,"row":3},{"value":["f",22],"depth":0,"type":"rowHeader","row":4},{"value":["Stark",22],"type":"data","depth":1,"row":5}]"

Totals functionality

QuickPivot should return row and column totals and have the option to turn them on/off. Should this be done in the quickpivot logic or can it be done in a custom aggregator?

Support Multiple Aggregation Dimensions

It would be great to have the type of functionality seen in this Pivot component:

Webix Pivot Component

Here, both GDP and OIL are aggregation dimensions, with configurable aggregators. I tried forking the library and working on it on my own, but I was unable to get it working on first pass. Any suggestions or recommendations on where to focus? Thanks!

Should pivot.getUniqueValues return unique values of the current pivot or original?

When adding a filter on a certain dimension and then going back to edit that same filter, I need access to all the original unique values associated with that dimension. I am keeping track of the selected values associated with the dimension in order to filter the data using those values and could add them back into the list of values to select from; however, I would not be able to maintain the original order of values to select from unless I alphabetized strings and sorted numbers from the start. Which perhaps we should do... Other pivots seem to.

Below is an example of the current implementation, where pivot.getUniqueValues returns the unique values based on the current pivot?

const dataArray = [ ['name', 'gender', 'house', 'age'], ['Jon', 'm', 'Stark', 14], ['Arya', 'f', 'Stark', 10], ['Cersei', 'f', 'Baratheon', 38], ['Tywin', 'm', 'Lannister', 67], ['Tyrion', 'm', 'Lannister', 34], ['Joffrey', 'm', 'Baratheon', 18], ['Bran', 'm', 'Stark', 8], ['Jaime', 'm', 'Lannister', 32], ['Sansa', 'f', 'Stark', 12] ];

const pivot = new pivot(dataArray, ['gender'], [], 'age', 'sum');

pivot.getUniqueValues('gender')
-> ["m", "f"]

pivot.filter('gender', ['m'], 'exclude')
pivot.getUniqueValues('gender')
-> ["f"]

Should filters stack / are they chainable?

Should filters stack / are they chainable? Or do we only allow one filter at a time?

const dataArray = [ ['name', 'gender', 'house', 'age'], ['Jon', 'm', 'Stark', 14], ['Arya', 'f', 'Stark', 10], ['Cersei', 'f', 'Baratheon', 38], ['Tywin', 'm', 'Lannister', 67], ['Tyrion', 'm', 'Lannister', 34], ['Joffrey', 'm', 'Baratheon', 18], ['Bran', 'm', 'Stark', 8], ['Jaime', 'm', 'Lannister', 32], ['Sansa', 'f', 'Stark', 12] ];

const testPivot = new pivot(dataArray, ['age'], ['house','gender'], [], 'sum');
testPivot.filter("house", ["Stark"], 'exclude')
testPivot.filter("gender", ["m"], 'exclude')

returns

"[{"value":["sum ","Stark","Baratheon"],"depth":0,"type":"colHeader","row":0},{"value":["sum ","f","f"],"depth":1,"type":"colHeader","row":1},{"value":["10",null,""],"type":"data","depth":0,"row":2},{"value":["12",null,""],"type":"data","depth":0,"row":3},{"value":["38","",null],"type":"data","depth":0,"row":4}]"

Which is the result of the second filter (first filter is not applied).

Filtering out all values returns empty array. Should return remaining unfiltered fields with 0 values.

Filtering out all values returns empty array. Should return remaining unfiltered fields with 0 values.

const dataArray = [ ['name', 'gender', 'house', 'age'], ['Jon', 'm', 'Stark', 14], ['Arya', 'f', 'Stark', 10], ['Cersei', 'f', 'Baratheon', 38], ['Tywin', 'm', 'Lannister', 67], ['Tyrion', 'm', 'Lannister', 34], ['Joffrey', 'm', 'Baratheon', 18], ['Bran', 'm', 'Stark', 8], ['Jaime', 'm', 'Lannister', 32], ['Sansa', 'f', 'Stark', 12] ];

const testPivot = new pivot(dataArray, ['house', 'gender'], [], 'age', 'sum', '');

testPivot.filter('gender', ['f','m'], 'exclude')

testPivot.data.table
returns []

Instead it should return
"[{"value":["",""],"depth":0,"type":"colHeader","row":0},{"value":["Baratheon",0],"type":"data","depth":0,"row":1},{"value":["Lannister",0],"type":"data","depth":0,"row":2},{"value":["Stark",0],"type":"data","depth":0,"row":3}]"

Or if this is a tremendous amount of work perhaps just the empty header.

'Include' filtering with values that are a part of the unique values of that field throws error

const dataArray = [
 ['name', 'gender', 'house', 'age'],
 ['Jon', 'm', 'Stark', 14],
 ['Arya', 'f', 'Stark', 10],
 ['Cersei', 'f', 'Baratheon', 38],
 ['Tywin', 'm', 'Lannister', 67],
 ['Tyrion', 'm', 'Lannister', 34],
 ['Joffrey', 'm', 'Baratheon', 18],
 ['Bran', 'm', 'Stark', 8],
 ['Jaime', 'm', 'Lannister', 32],
 ['Sansa', 'f', 'Stark', 12]
];

const pivot = new pivot(dataArray, ['gender'], [], 'age', 'count');

pivot.filter('gender', ['dogman'], 'include')

image

Aggregation type and aggregation category naming

If we pass undefined aggregation types and categories should we throw an error?

For example:
const examplePivot = new Pivot([['name', 'gender', 'house', 'age'],['Jon', 'm', 'Stark', 14],['Arya', 'f', 'Stark', 10],['Cersei', 'f', 'Baratheon', 38],['Tywin', 'm', 'Lannister', 67],['Tyrion', 'm', 'Lannister', 34],['Joffrey', 'm', 'Baratheon', 18],['Bran', 'm', 'Stark', 8],['Jaime', 'm', 'Lannister', 32],['Sansa', 'f', 'Stark', 12]],['name'],[], 'cat', 'dog')

image

examplePivot.data.table
image

So it ignores the aggregation category 'cat' and defaults to aggregationType 'count' which makes sense. But should we throw an error here? The aggregation category is either one of the available fields from the data headers or '' for count. And should it say 'count' instead of 'dog' for the aggregation type since it performed a count?

different behaviour between chrome and firefox with same dataset

In actual scenario the app paint three accumulated bar charts, in vue 3, composition API so with same dataset using a pivot object like this one let pivot = new Pivot(initalDataSet, ['quien'], ['cuando'], 'cuanto', 'sum') wich is a three objects with this aspect:

export interface IItem {
labels: string[];
datasets: Dataset[];
}

export interface Dataset {
label: string;
data: number[];
barThickness: number;
borderRadius: number;
backgroundColor: string;
}

Example, I'll shorten the dataset array to make it simpler. The app recieve N numbers of datasets to paint, so after using the pivot object one of the arrays in Mozilla Firefozx looks like this ->

0: "agestc"
1: Array [ {…} ]
2: Array [ {…} ]
3: Array [ {…} ]
4: Array [ {…} ]
5: Array [ {…} ]
6: Array [ {…} ]
7: Array [ {…} ]
8: Array [ {…} ]
9: Array [ {…} ]
10: Array [ {…} ]
11: Array [ {…} ]
12: Array [ {…} ]
13: Array [ {…} ]
14: Array [ {…} ]
15: ""
16: ""
17: ""
18: ""
19: ""
20: ""
21: ""
22: ""
23: ""
24: ""
25: ""
26: ""
27: ""
28: ""
29: ""
30: ""
31: ""
32: ""
33: ""
34: ""
35: ""
36: ""
37: ""
38: ""
39: ""
40: ""
41: ""
42: ""
43: ""
44: ""
45: ""
46: ""
47: ""
48: ""
49: ""
50: ""
51: ""
52: ""
53: ""
54: ""
55: ""
56: ""
57: ""
58: ""
59: ""
60: ""
61: ""​​​​
length: 62

In Google chrome looks like this ->

0: "agestc"
1: ""
2: ""
3: ""
4: ""
5: ""
6: [{…}]
7: ""
8: ""
9: ""
10: ""
11: ""
12: ""
13: ""
14: ""
15: ""
16: ""
17: ""
18: [{…}]
19: ""
20: [{…}]
21: ""
22: ""
23: ""
24: [{…}]
25: [{…}]
26: [{…}]
27: ""
28: ""
29: ""
30: [{…}]
31: [{…}]
32: ""
33: ""
34: ""
35: ""
36: [{…}]
37: ""
38: ""
39: ""
40: [{…}]
41: ""
42: [{…}]
43: [{…}]
44: ""
45: ""
46: ""
47: ""
48: ""
49: ""
50: ""
51: ""
52: ""
53: ""
54: [{…}]
55: ""
56: ""
57: ""
58: [{…}]
59: ""
60: ""
61: ""
length: 62

The problem is that after setting the requested data from the database, with the same pivot dataset object, Mozilla Firefox mix the positions of the array and Google chrome leave them intact.
After this the chart shows well in google chrome and wrong in Mozilla, The question is how can I achieve the expected effect as Google chrome does in Mozilla Firefox?

charts in Mozilla :
Dashboard App charts — Mozilla Firefox_001

charts in Chrome:
Dashboard App charts - Google Chrome_001

Reproduction

https://github.com/enlazoCtrl/charts here is the two vue classes that uses the quick-pivot library

Filtering out all data throw error

When providing filters that filter out all data, an error is thrown.

const dataArray = [
 ['name', 'gender', 'house', 'age'],
 ['Jon', 'm', 'Stark', 14],
 ['Arya', 'f', 'Stark', 10],
 ['Cersei', 'f', 'Baratheon', 38],
 ['Tywin', 'm', 'Lannister', 67],
 ['Tyrion', 'm', 'Lannister', 34],
 ['Joffrey', 'm', 'Baratheon', 18],
 ['Bran', 'm', 'Stark', 8],
 ['Jaime', 'm', 'Lannister', 32],
 ['Sansa', 'f', 'Stark', 12]
];

const pivot = new pivot(dataArray, ['gender'], [], 'age', 'count');
pivot.filter('gender', ['m', 'f'])

image

Filtering on value dimensions with string filter values instead of ints

When filtering on value fields, strings passed in as filters are not converted into ints. Should we do this in the pivot logic or on the front end? Numbers on the front-end are rendered as strings so when passed back as in a filter as a they do not match the respective int stored in the pivot.

const dataArray = [
 ['name', 'gender', 'house', 'age'],
 ['Jon', 'm', 'Stark', 14],
 ['Arya', 'f', 'Stark', 10],
 ['Cersei', 'f', 'Baratheon', 38],
 ['Tywin', 'm', 'Lannister', 67],
 ['Tyrion', 'm', 'Lannister', 34],
 ['Joffrey', 'm', 'Baratheon', 18],
 ['Bran', 'm', 'Stark', 8],
 ['Jaime', 'm', 'Lannister', 32],
 ['Sansa', 'f', 'Stark', 12]
];

const pivot = new pivot(dataArray, ['age'], [], 'age', 'sum');

// returns original pivoted data because it is excluding a string that does match the int 8 in the pivot
pivot.filter("age", ["8"], 'exclude')

// works
pivot.filter("age", [8], 'exclude')

Filtering / Sorting

I was thinking about the filtering and sorting logic. While it's feasible to do it on the front-end, should it be done on the back-end? I think it would be better to do on the back end since the groups of data have to be filtered / sorted.

TypeError: Object.values is not a function

Hi,
I'm using this in an application running in node (v6.10.2), was helped by it greatly, but after the change from using babel-polyfill to babel-runtime now I get:

TypeError: Object.values is not a function
at o (.../node_modules/quick-pivot/lib/quick-pivot.min.js:1:3952)
at i (.../node_modules/quick-pivot/lib/quick-pivot.min.js:1:4228)
at s (.../node_modules/quick-pivot/lib/quick-pivot.min.js:1:6506)
at new e (.../node_modules/quick-pivot/lib/quick-pivot.min.js:1:1158)

Upgrading to node 7 does fix the problem, is there an easier alternative?

Row and column total header

Should row and column totals both have blank headers, or text headers of 'Totals' similar to PivotTable.js? Currently row total header is blank and column total header has text of 'aggregated'. See screenshot below.

screen shot 2017-12-03 at 9 45 47 pm

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.