Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stacked area charts render with gaps when the X coordinates are not continuous #388

Closed
wylieconlon opened this issue Sep 23, 2019 · 15 comments · Fixed by #409 or #416
Closed

Stacked area charts render with gaps when the X coordinates are not continuous #388

wylieconlon opened this issue Sep 23, 2019 · 15 comments · Fixed by #409 or #416
Assignees
Labels
bug Something isn't working released Issue released publicly

Comments

@wylieconlon
Copy link

Describe the bug
Gaps appear in the rendering when you skip an X coordinate in your stacked area chart. It only appears in stacked areas, since stacked bars render correctly.

Screenshot 2019-09-23 14 08 34

To Reproduce
This is an example of discontinuous data:

      <AreaSeries
        splitSeriesAccessors={['split']}
        stackAccessors={['x']}
        id={getSpecId('y')}
        xAccessor={'x'}
        yAccessors={['y']}
        data={[
          {
            x: 5,
            y: 10,
            split: 'a',
          },
          {
            x: 5,
            y: 30,
            split: 'b',
          },
          {
            x: 10,
            y: 2,
            split: 'a',
          },
          // {
          //   x: 10,
          //   y: 3,
          //   split: 'b',
          // },
          {
            x: 20,
            y: 30,
            split: 'a',
          },
          {
            x: 20,
            y: 20,
            split: 'b',
          },
        ]}
        xScaleType={ScaleType.Linear}
        yScaleType={ScaleType.Linear}
      />

Expected behavior
With the data above, I would expect the chart library to insert an extra vertex at the missing X coordinates.

@wylieconlon wylieconlon added the bug Something isn't working label Sep 23, 2019
@nickofthyme nickofthyme self-assigned this Sep 25, 2019
@nickofthyme
Copy link
Collaborator

@markov00 would this be a non-standard behaviour through a prop or should it always ignore discontinuous data?

@wylieconlon
Copy link
Author

As a consumer of elastic-charts I would expect stacking to work regardless of the input data. I would expect that the stacking is always cumulative, so that every vertex in the bottom stack will create a vertex in stacks above.

@nickofthyme
Copy link
Collaborator

Ok cool, that makes sense! I'll make it happen. Thanks @wylieconlon

@markov00
Copy link
Member

markov00 commented Sep 27, 2019

@wylieconlon what is the expected output for the above example?

Do you expect that, by default, the missing value is configured as a zero as in the following screenshot
Screenshot 2019-09-27 at 15 11 50

Or something like this
Screenshot 2019-09-27 at 15 11 37

The second one shows better the fact that there is no value at x = 10, where the first imply that there is a value and it's 0.

I think we could go with something configurable by the consumer/user

@nickofthyme I think we can partially resume this: #55

@wylieconlon
Copy link
Author

@markov00 I see cases where both of those charts are correct. I just tried recreating this in google sheets and found that they do the first behavior, treating missing values as 0 and connecting the lines. Elasticsearch aggregations support both behaviors, they are null by default but can be configured to have a value: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-avg-aggregation.html#_missing_value

I actually think I was expecting a rendering that is in between the two, because the "gaps" rendering would look very strange in the example I gave at the top, or with any other stacks.

Imagine the shape I've drawn here, but with a fill underneath the dotted line:

65771757-2f08c480-e139-11e9-842a-ae84c6d2e4ff

@markov00
Copy link
Member

markov00 commented Oct 1, 2019

@wylieconlon I like the idea of having a dashed line that describe the missing part of the chart.
I think we can use a fitting function #55 to define the value of the missing point: null, 0, last available, the next available etc.

I think the segmented/dashed line can take a bit more time to implement because we need to separate that line from the rest of the chart but we can work on adding the fitting function to that.

@nickofthyme
Copy link
Collaborator

nickofthyme commented Oct 1, 2019

Based on slack/zoom conversations with @wylieconlon and @markov00

LineSeriesSpec and AreaSeriesSpec should allow the user to specify a fitting function to fill null values in the dataset. Similar to elastic/kibana#17717.

For the meantime, the style of the "fitted" line should be dashed and area fill, if applicable, will be the same as the "non-fitted" fill color. Later improvement could pass a style to be applied.

Edge cases:

  • Stacked areas where void is in lower series such that the upper series would potentially have to fill the void in the lower series.

image

Code
import React from 'react';
import {
  Axis,
  Chart,
  getAxisId,
  getSpecId,
  Position,
  ScaleType,
  Settings,
  LineSeries,
  AreaSeries,
  DataGenerator,
} from '../src';

const dg = new DataGenerator();
const data = dg.generateGroupedSeries(10);

export class Playground extends React.Component {
  render() {
    return (
      <>
        <div className="chart">
          <Chart className="story-chart">
            <Settings
              theme={{
                areaSeriesStyle: {
                  point: {
                    visible: true,
                  },
                },
              }}
            />
            <Axis
              id={getAxisId('bottom')}
              position={Position.Bottom}
              title={'Bottom axis'}
              showOverlappingTicks={true}
            />
            <Axis id={getAxisId('left')} title={'Left axis'} position={Position.Left} />
            <AreaSeries
              id={getSpecId('test')}
              xScaleType={ScaleType.Linear}
              yScaleType={ScaleType.Linear}
              xAccessor={'x'}
              yAccessors={['y']}
              splitSeriesAccessors={['g']}
              stackAccessors={['x']}
              data={data.map((d, i) => {
                if (i === 5) {
                  return {
                    ...d,
                    y: null,
                  };
                }
                return d;
              })}
            />
          </Chart>
        </div>
      </>
    );
  }
}

@wylieconlon
Copy link
Author

Looking at existing work in Kibana, I think this area chart rendering issue can also create single dots:

Screenshot 2019-10-02 14 36 46

@nickofthyme
Copy link
Collaborator

Yeah that's a good point, I think would be the case for fit of None.

On a related note...I think the should not be points for the fitted data points. This is misleading because it could be assumed as actual data points but they are not.

I was thinking to draw a line with not points for all fit functions. Then the line would be dashed and area filled below, depending on the fit type.

@markov00
Copy link
Member

markov00 commented Oct 3, 2019

@wylieconlon the example shown already works in elastic-chart (infra is using elastic charts). The problem here is more on how to handle stacked area chart more than single area chart that work as expected (the main difference is that the style of the area chart is configured to shoiw the area points)

@wylieconlon
Copy link
Author

@markov00 Sorry if I was unclear, but I showed that screenshot not because it's a problem in isolation but because I'm not sure what the correct stacking behavior would be there. Imagine that we're tracking total network traffic and want to split it by machine, and the traffic looks like above. How would it stack?

@markov00
Copy link
Member

markov00 commented Oct 8, 2019

@wylieconlon I'm working on a PR to fix that behaviour.
I will complete first a quick workaround/fix and then try to tackle the issue from a different prospective.

My quick fix will be: fill all the missing points with a 0 y value and hide the 0 point.

Screenshot 2019-10-08 at 18 01 14

I will work on adding a better representation of missing data points on area/line chart that will fill the gaps with "missing" areas:
Screenshot 2019-10-08 at 17 59 17

I've already partially implemented this second behaviour but we need to understand a bit better how to handle the case with curved area charts

@wylieconlon
Copy link
Author

@markov00 Thanks for the update! The "quick fix" behavior you've described will work for us as long as we are able to get it in for 7.5

markov00 added a commit to markov00/elastic-charts that referenced this issue Oct 8, 2019
When displaying a stacked area/line chart with multiple data sets we need to fill the dataset with
zeros on missing data points. The rendering is affected also: it will hide the filled missing point
but will continue to show the area beneath it.

fix elastic#388
markov00 added a commit that referenced this issue Oct 9, 2019
…#409)

When displaying a stacked area/line chart with multiple data sets we need to fill the dataset with zeros on missing data points. The rendering is affected also: it will hide the filled missing point but will continue to show the area beneath it.

fix #388
markov00 pushed a commit that referenced this issue Oct 9, 2019
# [13.5.0](v13.4.1...v13.5.0) (2019-10-09)

### Features

* **data:** fill datasets with zeros with missing points when stacked ([#409](#409)) ([ef84fd4](ef84fd4)), closes [#388](#388)
@markov00
Copy link
Member

markov00 commented Oct 9, 2019

🎉 This issue has been resolved in version 13.5.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@markov00 markov00 added the released Issue released publicly label Oct 9, 2019
nickofthyme added a commit that referenced this issue Nov 13, 2019
Add ability to fit data of non-stacked line and area charts with a specified fit function type
* add fit functions for null y1 values
* allow end values to be explicitly set as fallback
* add visual regression tests
* add unit tests and better testing utils

Note: Does not *yet* support stacked charts or `y0` values. This is a future enhancement is being tracked in #450.

related to #388
markov00 pushed a commit that referenced this issue Nov 13, 2019
# [14.1.0](v14.0.0...v14.1.0) (2019-11-13)

### Features

* fit functions for null y1 values ([#416](#416)) ([e083755](e083755)), closes [#450](#450) [#388](#388)
@markov00
Copy link
Member

🎉 This issue has been resolved in version 14.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

AMoo-Miki pushed a commit to AMoo-Miki/OpenSearch-Dashboards that referenced this issue Feb 10, 2022
# [13.5.0](elastic/elastic-charts@v13.4.1...v13.5.0) (2019-10-09)

### Features

* **data:** fill datasets with zeros with missing points when stacked ([opensearch-project#409](elastic/elastic-charts#409)) ([b989074](elastic/elastic-charts@b989074)), closes [opensearch-project#388](elastic/elastic-charts#388)
AMoo-Miki pushed a commit to AMoo-Miki/OpenSearch-Dashboards that referenced this issue Feb 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released Issue released publicly
Projects
None yet
3 participants