diff --git a/app/client/components/ChartView.ts b/app/client/components/ChartView.ts index 1c79772a..6343df8d 100644 --- a/app/client/components/ChartView.ts +++ b/app/client/components/ChartView.ts @@ -1,6 +1,6 @@ import * as BaseView from 'app/client/components/BaseView'; import {GristDoc} from 'app/client/components/GristDoc'; -import {sortByXValues} from 'app/client/lib/chartUtil'; +import {sortByXValues, uniqXValues} from 'app/client/lib/chartUtil'; import {Delay} from 'app/client/lib/Delay'; import {Disposable} from 'app/client/lib/dispose'; import {fromKoSave} from 'app/client/lib/fromKoSave'; @@ -352,6 +352,15 @@ function cssCheckboxRow(label: string, value: KoSaveableObservable, ... function basicPlot(series: Series[], options: ChartOptions, dataOptions: Partial): PlotData { trimNonNumericData(series); const errorBars = extractErrorBars(series, options); + + if (dataOptions.type === 'bar') { + // Plotly has weirdness when redundant values shows up on the x-axis: the values that shows + // up on hover is different than the value on the y-axis. It seems that one is the sum of all + // values with same x-axis value, while the other is the last of them. To fix this, we force + // unique values for the x-axis. + series = uniqXValues(series); + } + return { data: series.slice(1).map((line: Series): Data => ({ name: getSeriesName(line, series.length > 2), diff --git a/app/client/lib/chartUtil.ts b/app/client/lib/chartUtil.ts index f183bf60..130841ca 100644 --- a/app/client/lib/chartUtil.ts +++ b/app/client/lib/chartUtil.ts @@ -1,5 +1,7 @@ import {typedCompare} from 'app/common/SortFunc'; import {Datum} from 'plotly.js'; +import range = require('lodash/range'); +import uniqBy = require('lodash/uniqBy'); /** * Sort all values in a list of series according to the values in the first one. @@ -18,3 +20,14 @@ export function sortByXValues(series: Array<{values: Datum[]}>): void { s.values = indices.map((i) => values[i]); } } + +// creates new version of series that has a duplicate free version of the values in the first one. +export function uniqXValues(series: Array): Array { + if (!series[0]) { return []; } + const n = series[0].values.length; + const indexToKeep = new Set(uniqBy(range(n), (i) => series[0].values[i])); + return series.map((line: T) => ({ + ...line, + values: line.values.filter((_val, i) => indexToKeep.has(i)) + })); +}