Skip to content

Commit

Permalink
feat(bar_chart): allow grouping of datums within series
Browse files Browse the repository at this point in the history
Allows for grouping of datums within a series to enable global groups. Allow custom colors of
groupings.

BREAKING CHANGE: Color accesors is replaced with groupAccessors. DataSeriesColorsValues renamed to
DataSeriesValues, colorValues renamed to accessors and added group.

elastic#216
  • Loading branch information
nickofthyme committed Jul 2, 2019
1 parent c44f0fc commit 2a64288
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 195 deletions.
26 changes: 15 additions & 11 deletions src/lib/series/domains/y_domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,13 @@ export function getDataSeriesOnGroup(
function computeYStackedDomain(dataseries: RawDataSeries[], scaleToExtent: boolean): number[] {
const stackMap = new Map<any, any[]>();
dataseries.forEach((ds, index) => {
ds.data.forEach((datum) => {
const stack = stackMap.get(datum.x) || [];
stack[index] = datum.y1;
stackMap.set(datum.x, stack);
});
for (const [group, data] of ds.data) {
data.forEach((datum) => {
const stack = stackMap.get(datum.x) || [];
stack[index] = datum.y1;
stackMap.set(datum.x, stack);
});
}
});
const dataValues = [];
for (const stackValues of stackMap) {
Expand All @@ -126,12 +128,14 @@ function computeYStackedDomain(dataseries: RawDataSeries[], scaleToExtent: boole
function computeYNonStackedDomain(dataseries: RawDataSeries[], scaleToExtent: boolean) {
const yValues = new Set<any>();
dataseries.forEach((ds) => {
ds.data.forEach((datum) => {
yValues.add(datum.y1);
if (datum.y0 != null) {
yValues.add(datum.y0);
}
});
for (const [group, data] of ds.data) {
data.forEach((datum) => {
yValues.add(datum.y1);
if (datum.y0 != null) {
yValues.add(datum.y0);
}
});
}
});
if (yValues.size === 0) {
return [];
Expand Down
58 changes: 36 additions & 22 deletions src/lib/series/nonstacked_series_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,55 @@ export function formatNonStackedDataSeriesValues(dataseries: RawDataSeries[], sc
const formattedValue = formatNonStackedDataValues(dataseries[i], scaleToExtent);
formattedValues.push(formattedValue);
}

return formattedValues;
}

export function formatNonStackedDataValues(dataSeries: RawDataSeries, scaleToExtent: boolean): DataSeries {
const len = dataSeries.data.length;
let i;
const formattedValues: DataSeries = {
keys: dataSeries.keys,
specId: dataSeries.specId,
seriesKey: dataSeries.seriesKey,
data: [],
data: new Map(),
};
for (i = 0; i < len; i++) {
const data = dataSeries.data[i];
const { x, y1, datum } = data;
let y0: number | null;
if (y1 === null) {
y0 = null;
} else {
if (scaleToExtent) {
y0 = data.y0 ? data.y0 : y1;

for (const [group, series] of dataSeries.data) {
const len = series.length;
const formatted = [];

for (let i = 0; i < len; i++) {
const data = series[i];
const { x, y1, datum, xAccessor, yAccessor } = data;
let y0: number | null;
if (y1 === null) {
y0 = null;
} else {
y0 = data.y0 ? data.y0 : 0;
if (scaleToExtent) {
y0 = data.y0 ? data.y0 : y1;
} else {
y0 = data.y0 ? data.y0 : 0;
}
}

const formattedValue: DataSeriesDatum = {
x,
y1,
y0,
xAccessor,
yAccessor,
initialY1: y1,
initialY0: data.y0 == null || y1 === null ? null : data.y0,
datum,
};
formatted.push(formattedValue);
}

if (!formattedValues.data.has(group)) {
formattedValues.data.set(group, []);
}

const formattedValue: DataSeriesDatum = {
x,
y1,
y0,
initialY1: y1,
initialY0: data.y0 == null || y1 === null ? null : data.y0,
datum,
};
formattedValues.data.push(formattedValue);
formattedValues.data.get(group)!.push(...formatted);
}

return formattedValues;
}
7 changes: 3 additions & 4 deletions src/lib/series/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { isLogarithmicScale } from '../utils/scales/scale_continuous';
import { Scale, ScaleType } from '../utils/scales/scales';
import { CurveType, getCurveFactory } from './curves';
import { LegendItem } from './legend';
import { DataSeriesDatum } from './series';
import { DataSeriesDatum, RawDataSeriesDatum } from './series';
import { belongsToDataSeries } from './series_utils';
import { DisplayValueSpec } from './specs';
import { Accessor, getAccessorValues, AccessorFn } from '../utils/accessor';
Expand Down Expand Up @@ -209,7 +209,7 @@ export function renderBars(
seriesKey: any[],
displayValueSettings?: DisplayValueSpec,
seriesStyle?: CustomBarSeriesStyle,
groupAccessors?: (Accessor | AccessorFn)[],
groupAccessors?: (Accessor | AccessorFn<RawDataSeriesDatum>)[],
): RenderBarsGeometry {
const indexedGeometries = new Map<any, IndexedGeometry[]>();
const xDomain = xScale.domain;
Expand Down Expand Up @@ -284,9 +284,8 @@ export function renderBars(
: undefined;

if (groupAccessors) {
const [colorGroup] = getAccessorValues(datum!.datum, groupAccessors);
const [colorGroup] = getAccessorValues(datum, groupAccessors);
if (colorGroup) {
console.log(colorGroup);
color = colorGroup;
}
}
Expand Down
42 changes: 29 additions & 13 deletions src/lib/series/series.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export interface RawDataSeriesDatum {
y1: number | null;
/** the optional y0 metric, used for bars or area with a lower bound */
y0?: number | null;
/** main(x) accessor value */
xAccessor: Accessor;
/** secondary(y) accessor value */
yAccessor: Accessor;
/** the datum */
datum?: any;
}
Expand All @@ -36,13 +40,13 @@ export interface RawDataSeries {
specId: SpecId;
keys: any[];
seriesKey: string;
data: RawDataSeriesDatum[];
data: Map<string, RawDataSeriesDatum[]>;
}

export type DataSeries = Merge<
RawDataSeries,
{
data: DataSeriesDatum[];
data: Map<string, DataSeriesDatum[]>;
}
>;

Expand All @@ -66,6 +70,8 @@ export interface DataSeriesValues {
specSortIndex?: number;
}

export const BASE_GROUP_KEY = '__base__';

export function getSeriesIndex(series: DataSeriesValues[] | null, value: DataSeriesValues): number {
if (!series) {
return -1;
Expand Down Expand Up @@ -97,28 +103,24 @@ export function splitSeries(

data.forEach((datum) => {
const splitSeriesKeys = getAccessorValues(datum, splitSeriesAccessors);
const [groupKey] = getAccessorValues(datum, groupAccessors);

if (isMultipleY) {
yAccessors.forEach((accessor, index) => {
const seriesKeys = [...splitSeriesKeys, accessor];
const seriesKey = getSeriesKey(specId, seriesKeys);

console.log('nick - 1', seriesKey);

const cleanedDatum = cleanDatum(datum, xAccessor, accessor, y0Accessors && y0Accessors[index]);
const [groupKey] = getAccessorValues(cleanedDatum, groupAccessors);
splitSeriesLastValues.set(seriesKey, cleanedDatum.y1);
xValues.add(cleanedDatum.x);
updateSeriesMap(series, seriesKeys, seriesKey, cleanedDatum, specId);
updateSeriesMap(series, seriesKeys, seriesKey, cleanedDatum, specId, groupKey);
});
} else {
const seriesKey = getSeriesKey(specId, splitSeriesKeys);

console.log('nick - 2', seriesKey);
const cleanedDatum = cleanDatum(datum, xAccessor, yAccessors[0], y0Accessors && y0Accessors[0]);
const [groupKey] = getAccessorValues(cleanedDatum, groupAccessors);
splitSeriesLastValues.set(seriesKey, cleanedDatum.y1);
xValues.add(cleanedDatum.x);
updateSeriesMap(series, splitSeriesKeys, seriesKey, cleanedDatum, specId);
updateSeriesMap(series, splitSeriesKeys, seriesKey, cleanedDatum, specId, groupKey);
}
});

Expand All @@ -139,16 +141,23 @@ function updateSeriesMap(
seriesKey: string,
datum: RawDataSeriesDatum,
specId: SpecId,
groupKey: string = BASE_GROUP_KEY,
): Map<string, RawDataSeries> {
const series = seriesMap.get(seriesKey);
if (series) {
series.data.push(datum);
if (series.data.has(groupKey)) {
series.data.get(groupKey)!.push(datum);
} else {
series.data.set(groupKey, [datum]);
}
} else {
const data = new Map<string, RawDataSeriesDatum[]>();
data.set(groupKey, [datum]);
seriesMap.set(seriesKey, {
specId,
keys,
seriesKey,
data: [datum],
data,
});
}
return seriesMap;
Expand All @@ -167,7 +176,14 @@ export function getSeriesKey(specId?: SpecId, accessors: any[] = []): string {
function cleanDatum(datum: Datum, xAccessor: Accessor, yAccessor: Accessor, y0Accessor?: Accessor): RawDataSeriesDatum {
const x = datum[xAccessor];
const y1 = datum[yAccessor];
const cleanedDatum: RawDataSeriesDatum = { x, y1, datum, y0: null };
const cleanedDatum: RawDataSeriesDatum = {
x,
y1,
datum,
xAccessor,
yAccessor,
y0: null,
};
if (y0Accessor) {
cleanedDatum.y0 = datum[y0Accessor];
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/series/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Omit } from '../utils/commons';
import { AnnotationId, AxisId, GroupId, SpecId } from '../utils/ids';
import { ScaleContinuousType, ScaleType } from '../utils/scales/scales';
import { CurveType } from './curves';
import { DataSeriesValues } from './series';
import { DataSeriesValues, RawDataSeriesDatum } from './series';

export type Datum = any;
export type Rotation = 0 | 90 | -90 | 180;
Expand Down Expand Up @@ -97,7 +97,7 @@ export interface SeriesAccessors {
/** An array of fields thats indicates the stack membership */
stackAccessors?: Accessor[];
/** An optional array of field name thats indicates the color grouping */
groupAccessors?: (Accessor | AccessorFn)[];
groupAccessors?: (Accessor | AccessorFn<RawDataSeriesDatum>)[];
}

export interface SeriesScales {
Expand Down
Loading

0 comments on commit 2a64288

Please sign in to comment.