I wrote an objective-c method to return a beautiful axis scale and good ticks for the given minimum and maximum values of your dataset:
- (NSArray*)niceAxis:(double)minValue :(double)maxValue { double min_ = 0, max_ = 0, min = minValue, max = maxValue, power = 0, factor = 0, tickWidth, minAxisValue = 0, maxAxisValue = 0; NSArray *factorArray = [NSArray arrayWithObjects:@"0.0f",@"1.2f",@"2.5f",@"5.0f",@"10.0f",nil]; NSArray *scalarArray = [NSArray arrayWithObjects:@"0.2f",@"0.2f",@"0.5f",@"1.0f",@"2.0f",nil]; // calculate x-axis nice scale and ticks // 1. min_ if (min == 0) { min_ = 0; } else if (min > 0) { min_ = MAX(0, min-(max-min)/100); } else { min_ = min-(max-min)/100; } // 2. max_ if (max == 0) { if (min == 0) { max_ = 1; } else { max_ = 0; } } else if (max < 0) { max_ = MIN(0, max+(max-min)/100); } else { max_ = max+(max-min)/100; } // 3. power power = log(max_ - min_) / log(10); // 4. factor factor = pow(10, power - floor(power)); // 5. nice ticks for (NSInteger i = 0; factor > [[factorArray objectAtIndex:i]doubleValue] ; i++) { tickWidth = [[scalarArray objectAtIndex:i]doubleValue] * pow(10, floor(power)); } // 6. min-axisValues minAxisValue = tickWidth * floor(min_/tickWidth); // 7. min-axisValues maxAxisValue = tickWidth * floor((max_/tickWidth)+1); // 8. create NSArray to return NSArray *niceAxisValues = [NSArray arrayWithObjects:[NSNumber numberWithDouble:minAxisValue], [NSNumber numberWithDouble:maxAxisValue],[NSNumber numberWithDouble:tickWidth], nil]; return niceAxisValues; }
You can call the method as follows:
NSArray *niceYAxisValues = [self niceAxis:-maxy :maxy];
and get the axis setting:
double minYAxisValue = [[niceYAxisValues objectAtIndex:0]doubleValue]; double maxYAxisValue = [[niceYAxisValues objectAtIndex:1]doubleValue]; double ticksYAxis = [[niceYAxisValues objectAtIndex:2]doubleValue];
Just in case, if you want to limit the number of ticks of the axis, do the following:
NSInteger maxNumberOfTicks = 9; NSInteger numberOfTicks = valueXRange / ticksXAxis; NSInteger newNumberOfTicks = floor(numberOfTicks / (1 + floor(numberOfTicks/(maxNumberOfTicks+0.5)))); double newTicksXAxis = ticksXAxis * (1 + floor(numberOfTicks/(maxNumberOfTicks+0.5)));
The first part of the code is based on a calculation that I found here to calculate a beautiful graph scale and ticks similar to excel graphs. It works great for all types of datasets. Here is an example iPhone implementation:
