Core Plot - bar chart with average horizontal line
Asked Answered
O

3

6

Is there a way to add an average horizontal line (or a whatever single line) to a bar chart graph using core plot framework?

Thanks.

Optimism answered 21/3, 2012 at 10:20 Comment(2)
because I have questions with no answers provided...Optimism
yeah you are right, I have looked through your questions and found you very unfortunate.Piggott
P
6

One way of doing this is by using CPTScatterPlot:

Add Following lines to your code after you have initialized and added your bar plot(or what ever your actual data plot is) to your graph.

// Before following code, initialize your data, actual data plot and add plot to graph

CPTScatterPlot *dataSourceLinePlot = [[[CPTScatterPlot alloc] init] autorelease];
CPTMutableLineStyle * lineStyle                      = [CPTMutableLineStyle lineStyle];
lineStyle.lineWidth              = 3.f;
lineStyle.lineColor              = [CPTColor blackColor];
lineStyle.dashPattern            = [NSArray arrayWithObjects:[NSNumber numberWithFloat:3.0f], [NSNumber numberWithFloat:3.0f], nil];
dataSourceLinePlot.dataLineStyle = lineStyle;
dataSourceLinePlot.identifier    = @"horizontalLineForAverage";
dataSourceLinePlot.dataSource    = self;
[barChart addPlot:dataSourceLinePlot toPlotSpace:plotSpace];

Then add datasource methods, in my case I have set the datasource in above code to self, so I am defining datasource methods in the same file:

-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{   
// Note this method will return number of records for both my actual plot, and for scattered plot which is used to draw horizontal average line. For latter, this will decide the horizontal length of your line
    return [myDataArray count];
}

-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
    NSDecimalNumber *num = nil;

        // If method is called to fetch data about drawing horizontal average line, then return your generated average value.
    if( plot.identifier==@"horizontalLineForAverage")
    {
        if(fieldEnum == CPTScatterPlotFieldX )
        {
                    // this line will remain as it is
            num =(NSDecimalNumber *)[NSDecimalNumber numberWithDouble:index];
        }
        else
        {
            num = (NSDecimalNumber *) myDataAverageValue;// Here you generate average value for location of horizontal line. You should edit this line only;
        }
    }
// handle other cases and return data for other plots       
    return num;
}
Piggott answered 11/4, 2012 at 17:3 Comment(3)
You can't compare a String in this way: plot.identifier==@"horizontalLineForAverage" change to [plot.identifier isEqual: @"horizontalLineForAverage"]Epinasty
@AndrewS Compiler uniquifies references to same string. Please see this answer: #3704054Piggott
I prefer this to Eric's approach, because it treats plots equally, where they share the same start and end point. If these points change, the average line will follow.Homestretch
C
1

Yes. Add a scatter plot to the graph and give it two data points—one at each end of the desired line.

Cowboy answered 22/3, 2012 at 0:33 Comment(2)
hello @Eric Skroch I don't understand this line num = (NSDecimalNumber *) myDataAverageValue; would u pls tell me with some example , what i can replace with myDataAverageValue. Thanks..Erminiaerminie
It's the y-value for the plot, encoded in an NSDecimalNumber.Cowboy
U
0
    CPTFill *bandFill = [CPTFill fillWithColor:[[CPTColor blackColor] colorWithAlphaComponent:1]];
    [y addBackgroundLimitBand:[CPTLimitBand limitBandWithRange:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(800) length:CPTDecimalFromDouble(1.5)] fill:bandFill]];

and

-(CPTPlotRange *)plotSpace:(CPTPlotSpace *)space willChangePlotRangeTo:(CPTPlotRange *)newRange forCoordinate:(CPTCoordinate)coordinate
{
    if (self.segment.selectedSegmentIndex == 2) {
        if (coordinate == CPTCoordinateY) {

            //NSLog(@"%f=>%f",self.yRange.lengthDouble,newRange.lengthDouble);

            CPTGraph* graph = space.graph;
            CPTXYAxisSet *axisSet = (CPTXYAxisSet *)graph.axisSet;
            CPTXYAxis *y = axisSet.yAxis;
            NSArray *bands = y.backgroundLimitBands;
            for (CPTLimitBand *band in bands) {
                [y removeBackgroundLimitBand:band];
            }

            CPTFill *bandFill = [CPTFill fillWithColor:[[CPTColor blackColor] colorWithAlphaComponent:1]];
            [y addBackgroundLimitBand:[CPTLimitBand limitBandWithRange:[CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(800) length:CPTDecimalFromDouble(1.5 * newRange.lengthDouble / 1200)] fill:bandFill]];
        }

    }

    return newRange;

}

please reference the "AxisDemo" section of the official sample "Plot_Gallery_iOS"

Unconditioned answered 12/11, 2014 at 1:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.