Charts 3.0 unable to draw discontinuous line chart

Created on 21 Nov 2016  路  25Comments  路  Source: danielgindi/Charts

I need to be able to draw an incomplete chart. That is, a complete x axis but a half complete y axis.

In previous versions, I would just have to add the labels to the x axis, which would render a full x axis.

Then I would need to add the half complete y values to the chart, then the chart would render the half complete y values but still the full x axis. I don't see a way to do this in 3.0 since using a nil value in place of y is not allowed as it is expecting a double value:

for (int i = 0; i < pricesArray.count; i++){
  double price = pricesArray[i][@"price"];
  [chartValues addObject:[[ChartDataEntry alloc] initWithX:i y:price]];
}

I need to add an x data point with a nil y value. Please advise.

Most helpful comment

@CAPIStkidd how do I make blank entries? Creating ChartDataEntry looks like it forces you to give it a double value, which does draw an incomplete chart the way I want it to but it messes with the scale of the y axis if I for example give the blank entries all 0 values.

All 25 comments

I have this problem, too.

This is a side effect of how the library changed how it does labeling.

The workaround for now is to make a second dataset with blank entries (so if you're wanting 100 entries and only 75 are drawn, make a second dataset with 25 entries, numbered 75-99) and add it as well.

@CAPIStkidd how do I make blank entries? Creating ChartDataEntry looks like it forces you to give it a double value, which does draw an incomplete chart the way I want it to but it messes with the scale of the y axis if I for example give the blank entries all 0 values.

@edalford11 you can use multiple data sets to simulate the breaking lines. In Chart 3.0, you can specify the x values directly, not index any more, so it should be fine.
I used to implement line breaking in Chart 2.x, however in Chart 3.0, I am thinking using multiple data sets is better?

@liuxuan30 I think you misinterpreted my last question. Using multiple data sets does work for breaking lines, but it messes with the scale of the y axis because the library forces you to put in a numeric value for the y values, which messes up the chart as a whole. If ChartDataEntry allowed you to put in EMPTY y values, then this approach would work. As I see it right now, the 3.0 version has disallowed line breaking charts because of this.

I have the same issue here. Don't know why this issue is closed.

@edalford11 are you saying 2.x version can support line breaking by using multiple data sets? I didn't try it yet, but from my understanding, all the data sets share the same x axis and y axis, so the xMin, xMax, yMin, yMax should not be impacted or messed up.

Let's say I want to break one line (1,1) -> (10,10) into two like: (1,1) -> (2,5), (3,6) -> (10,10)
So data set A:(1,1),(2,5); and data set B: (3,6), (10,10). Chart 3.0 should handle this two sets and draw lines respectively in x axis roughly [1,6], y axis [1,10]. I don't see it messes any y axis scale or min/max value.

Am I misunderstanding anything, or your discontinuous line chart is not what I meant 'breaking lines'?

The discontinuous line chart we meant is not 'breaking lines'. It means there are some data have x-axis values , but the y-axis values are nil. We can do that in Charts 2.0. but can't do that in Charts 3.0.
For example, there are 12 months in the x-axis, only 2 of them have y-axis value, others is nil. I want to draw a 12-month chart, not a 2-month chart. How to do it ?

@lightwindy maybe it's different terms, but from what you said, they are the same - https://github.com/danielgindi/Charts/issues/280

How did you do it in Chart 2.0? Overriding line chart renderer or multiple data sets? As I said above, we could use two data sets to simulate the gap between two lines. It's complicated I admit. Overrding the line chart renderer is harder, but also flexible.

In chart 3.0, yes, now every entry takes x and y, which means jumping is not possible for now.

In Charts 2.0, we can give the x-axis value and y-axis value respectively. Firstly, we can give the x-axis value and formatted them. Then give the y-axis value contain (y-value & x-index).
See following:

  1. xVals.append(Formatted Data)
  2. yVals.append(ChartDataEntry(value: Double, xIndex: Int))
  3. LineChartDataSet(yVals: yVals)
  4. LineChartData(xVals: xVals, dataSets: dataSets)

@liuxuan30 Let's say you have a LineChartDataSet, which is the set you want to be visible on the chart. The solution you suggested is to create a second LineChartDataSet, which will serve as the invisible line set that makes the line chart look discontinuous. This works but the problem is let's say the first LineChartDataSet has a y value range of 300 to 400. We are forced to give the second LineChartDataSet y values. If we give it say all 0's, the range of the y axis now becomes 0-400, which DOES screw up the scale of the y axis and the chart ends up drawing in a very non granular way. The second LineChartDataSet needs to have EMPTY y values such that the chart does not change the scale based on those y values. This was easily done in 2.0.

My temporary solution is to make sure the invisible LineChartDataSet has y values that are somewhere in the middle of the range of the first LineChartDataSet and set lineWidth to 0 so it doesn't draw, which keeps the scale of the y axis normal. Event though this works, it's not an ideal solution so I'd imagine we'd want to get back to more of the solution that 2.0 had for discontinuous line charts.

@edalford11 I think you misunderstood.
What I mentioned is that, every data set you created is visible;
say we have two lines, which is discontinuous:
The first line is connecting (0,1) to (2,3)
The second line is connecting (4,4) to (7, 6).

As you can see, (2,3) and (4,4) have gap.

Here's an example:
dl
I just set different x value for set 1 and set 2:

    for (int i = 0; i < count; i++)
    {
        if (i < count / 2) {
            double val = arc4random_uniform(range) + 3;
            [values addObject:[[ChartDataEntry alloc] initWithX:i y:val]];
        } else {
            double val = arc4random_uniform(range) + 3;
            [values2 addObject:[[ChartDataEntry alloc] initWithX:i+5 y:val]];
        }
    }

I did a dirty trick to make a gap by +5 (after the first gap, there is no more gap since the dot is connected).
This two-set trick make a discontinuous line had one defect: the x animation, so if you need x animation, it will have two lines draws simultaneously.

I used to override the line chart renderer to support this feature in Chart 2.0, however, it has pains while considering filling the rect. I think it's a better solution, but also a tough feature to implement.

You can take a look at https://github.com/danielgindi/Charts/issues/280, that's where we used to talk about this. Someone filed a PR, however for some reason it is closed by the author.
@danielgindi suggested to use the multiple data sets way to do it. But I guess he forgot the x animation.
Still, I guess it's a great feature to have by not using multiple data sets

About the x animation, I just come up with a quick fix: override the animator, to draw the data sets sequentially.

@liuxuan30 that makes sense but what I'm trying to do is not have the trailing data visible so this trick doesn't really work. In your example, the second data set needs to be completely invisible while keeping the same length of the x axis, which is why I'm saying we need the ability to add y values such that the y axis ignores the values when scaling.

I am kind of lost here.. You don't want the second line visible but keep the x axis the same min/max? It looks not like discontinuous lines..

Why not just set axis max value to be a large value, like 2x of your entry max value? So you have a plenty of space after your line?

A screenshot may help me understand.

The x axis labels are made up of timestamps. It's a stock chart, which shows the x axis from market open (9:30am) to market close (4:00pm). The y values extend along the x axis as the day goes on. Thus the line won't complete on the chart until 4:00pm.

I think you understand exactly how the chart is to be built at this point. You mentioned setting a max value on the x axis. Can you please explain how you do that? We are forced to make ChartDataEntry objects in order to build the x and y axis. I don't see how the chart would be smart enough to show this kind of chart by just setting a max value on the x axis.

'stock chart' do explain what you need. What I would try is this:
1 set xAxis max is like 4:00 pm value
2 add entries like I did above, e.g.

    _chartView.xAxis.axisMaximum = 8;
    for (int i = 0; i < 8; i++)
    {
        if (i < 8 / 2) {
            double val = arc4random_uniform(range) + 3;
            [values addObject:[[ChartDataEntry alloc] initWithX:i y:val]];
        }
    }

I just make a quick tweak in ChartsDemo, it looks like (it has a slow animation, which I don't know why yet):
image

Can this solve your problem?

The idea will be when you get new data you just update or create a new data and set it again, so it will 'grow' until 4:00pm

Your example you are setting axis labels to numbers. I don't see how this would work when the x axis labels are string values. axisMaximum only accepts double values anyway.

it's just a showcase how to get the visual effect for 'discontinuous line'. Since x is double and we uses valueFormatter, we can map [xMin, xMax] to [9:00am, 4:00pm] right? Formatting is another topic

Has anything changed since this thread was closed? Does the newest version of Charts support gaps in a dataset?

@edalford11 Eric, did you ever figure out how to do this?

@JCMcLovin I was able to achieve this by creating 2 separate LineChartDataSet objects.

LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithValues:chartValues label:@"Price"];
LineChartDataSet *set2 = [[LineChartDataSet alloc] initWithValues:emptyChartValues label:nil];

Where chartValues and emptyChartValues are arrays of ChartDataEntry objects. When adding both sets to an an array named dataSets (order matters for which dataset gets displayed first), they can be added to the chart like so.

LineChartData *data = [[LineChartData alloc] initWithDataSets:dataSets];

This displays a discontinuous chart the way I wanted.

I know I know obj-c gross.

@edalford11 Thanks, Eric. I guess I'll have to give that a try.

Also, 馃憤 on this:

I know I know obj-c gross.

Hi. I hope my message finds all of you well amid this global crisis.

I am using latest version of chart library to plot a line chart.

My graph shows months till Feb21. I don't want to show 'zero' values for all future months. It should be blank. Thats what I want to achieve.

I would need little guidance on how to make it.

Screen Shot 2020-04-02 at 9 41 51 AM

Was this page helpful?
0 / 5 - 0 ratings

Related issues

deepumukundan picture deepumukundan  路  3Comments

PrashantKT picture PrashantKT  路  3Comments

heumn picture heumn  路  3Comments

kirti0525 picture kirti0525  路  3Comments

Shunshine07 picture Shunshine07  路  3Comments