1
votes

I have a graph with multiple scatter plots in same plot area. X axis always is fixed with the dates of month 1-31. For some days there's no y-values (as you can see in the image)... but I need to join these points by line (eg: point 1 and 12 then 12 and 16 ...).

Image : enter image description here

This is the array I passed as the plot records

arrType1 = [[NSMutableArray alloc]initWithObjects:@"123",[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],@"234",[NSNull null],@"34",@"69",[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],@"45",[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],@"23", nil];

core-plot datasource methods

#pragma mark - CPTPlotDataSource methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
    return [[[CPDStockPriceStore sharedInstance] datesInMonth] count];
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSInteger valueCount = [[[CPDStockPriceStore sharedInstance] datesInMonth] count];
switch (fieldEnum) {
    case CPTScatterPlotFieldX:
        if (index < valueCount) {
            return [NSNumber numberWithUnsignedInteger:index];
        }
        break;

    case CPTScatterPlotFieldY:
        if ([plot.identifier isEqual:CPDTickerSymbolAAPL] == YES) {

            return [arrType1 objectAtIndex:index];
        }

        else if ([plot.identifier isEqual:CPDTickerSymbolGOOG] == YES) {

            return [arrType2 objectAtIndex:index];
        }

        else if ([plot.identifier isEqual:CPDTickerSymbolMSFT] == YES) {

            return [arrType3 objectAtIndex:index];
        }
        break;
}
    return [NSDecimalNumber zero];
}

How can I do It? Any ideas...

3
it doesn't make sense, because if there would be a line between 1st day and 12th day, it means that for second day you will not have null, but a little bit bigger value than on first day. - iOS Dev
@StanleyKubrick Theoretically yes. But my requirement is to join those two points even the middle points doesn't have values. (I think you got my point, basically I want a continuous scatter) - smartsanja

3 Answers

1
votes

I don't think you understood how Coreplot works. You don't need to provide a value for each x Coordinate. You just provide Coreplot with the x and corresponding y coordinates for the data points you want to add. Are you using the plot data source implementations? If So please post your implementation.

As a quick fix just leave out the NSNull instances in your array and the points will connect.

Basically lets say you have 3 Datapoints:

  1. x = 1 and y = 31
  2. x = 15 and y = 20
  3. x= 25 and y=22

To get that right you will only need these 3 to your graph and nothing else. To do that you could for example add them to an array of dictionary(as it is done in the core plot example project!)

NSMutableArray *theDataPoints = [NSMutableArray new];
[theDataPoints addObject:@{@"x": @(1),@"y" : @(31)}];
[theDataPoints addObject:@{@"x": @(15),@"y" : @(20)}];
[theDataPoints addObject:@{@"x": @(25),@"y" : @(22)}];

then in your Data Source Methods return the count of the Array as the NumberOfRecords:

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
    return [theDataPoints count];
}

and in your numberForPlot:field:recordIndex: function:

you first access your theDataPoints Array by Index:

NSDictionary *currentDataPoint = [theDataPoints objectAtIndex:index];

then calculate the right Dictionary Key to Access (whether you are looking for the X or the Y Value)

NSString *theKey;
if(fieldEnum == CPTScatterPlotFieldX){
    theKey = @"x";
}
else if(fieldEnum == CPTScatterPlotFieldY){
    theKey = @"y";
}
else{
    //throw an Error here
}

and finally get the NSNumber you want to return from that NSDictionary and return it.

NSNumber *theNumber = [currentDataPoint objectForKey:theKey];
return theNumber;

This will result in exactly the Graph you want with only the 3 Data Points Displayed and all of them connected.

On a side note. Since your Plot is basically displaying a value correlated to a date you might want to have a look at DatePlot Example in the Coreplot Example Workspace provided with the Framework download.

Anyway i hope i could help.

0
votes

I have only one option in mind: create another array from original data array, where null objects will be replaced by right value in order to draw a line between points, and this array will be used in core plot datasource:

//original array:
arrType1 = [[NSMutableArray alloc] initWithObjects:@"123",[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],@"234",[NSNull null],@"34",@"69",[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],@"45",[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],[NSNull null],@"23", nil];

//datasource array:
dataSourceArray = [[NSMutableArray alloc] initWithObjects:@(123),@(123 + ((234-123)/11)*1),@(123 + ((234-123)/11)*2),@(123 + ((234-123)/11)*3),@(123 + ((234-123)/11)*4),@(123 + ((234-123)/11)*5),@(123 + ((234-123)/11)*6),@(123 + ((234-123)/11)*7),...,@(234),..., nil]; 
//11 is the number of first null intervals.

You need to write an universal algorithm according to example above.

0
votes

The problem you're having comes from a misunderstanding of the meaning of recordIndex in the numberForPlot:field:recordIndex: callback. It can be summed up as follows: recordIndex is not x. Instead, this method is asking you to take recordIndex, index into the appropriate record, and return the value of x (assuming it's asking for CPTScatterPlotFieldX), which you may have to calculate in some way.

This bit me, too, even though it's embarrassingly obvious in hindsight. If you followed the Ray Wenderlich tutorials on Core Plot, those always return recordIndex when CPTScatterPlotFieldX is requested. This is why I kept thinking of recordIndex as x (as apparently many people new to Core Plot do). But you can return any value you wish.