I want to create a line graph but the range of numbers are different sometimes its like :
1,2,5,8,10
and sometimes its like :
-5 , -1 , 4 , 5, 15 , 8 ,20 ,...
by studying excel and openoffice I understand that they can indicate a range something like :
minNumber - k to maxNumber + k
and they divide the Y axis into equal area.
is there any specific formula for doing these things ?
When I looked at this problem I found that commercial products do a nice job of extending the range just enough to achieve pleasingly nice round numbers for their tick marks. If this is something you are interested in, take a look at this C# code that I wrote to try out different algorithms:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TickPicker
{
class TickPicker
{
double tickLow;
double tickHigh;
double tickUnit;
double tickCount;
//static double[] targetUnits = { 1, 2, 5, 10 };
static double[] targetUnits = { 1, 2, 2.5, 5, 10 };
static int[] roundFactors = { 1, 5, 4, 2, 1 };
//static double[] targetUnits = { 1, 1.5, 2.5, 5, 10 };
//static double[] targetUnits = { 1, 1.25, 2, 2.5, 5, 10 };
//static double[] targetUnits = { 1, 1.25, 1.5, 2, 2.5, 5, 10 };
//static double[] targetUnits = { 1, 1.25, 2, 5, 10 };
//static double[] targetUnits = { 1, 1.25, 1.5, 2, 5, 10 };
static double[] targetLogs = arrayLog(targetUnits);
TickPicker(double low, double high, int tickCountGoal)
{
double range = high - low;
double divGoal = range / (tickCountGoal - 2);
double logGoal = Math.Log10(divGoal);
double powerFactor = Math.Floor(logGoal);
logGoal = logGoal - powerFactor;
int closestIndex = findClosest(targetLogs, logGoal);
tickUnit = targetUnits[closestIndex] * (Math.Pow(10, powerFactor));
// Ensure the actual range encompasses the intended range
// The roundFactor discourages the .5 on the low and high range
int roundFactor = roundFactors[closestIndex];
tickLow = Math.Floor(low / tickUnit / roundFactor) * tickUnit * roundFactor;
tickHigh = Math.Ceiling(high / tickUnit / roundFactor) * tickUnit * roundFactor;
tickCount = (tickHigh - tickLow) / tickUnit;
}
static double[] arrayLog(double[] inputs)
{
double[] retVal = new double[inputs.Length];
int x = 0;
foreach (double input in inputs)
{
retVal[x] = Math.Log10(inputs[x]);
x++;
}
return retVal;
}
static int findClosest(double[] candidates, double input)
{
int low = 0;
for(int i = 1; i < candidates.Length && input > candidates[i]; i++)
{
low = i;
}
int high = low + 1;
return candidates[high] - input < input - candidates[low] ? high : low;
}
static void testPicker(double low, double high, int tickCountGoal)
{
TickPicker picker = new TickPicker(low, high, tickCountGoal);
System.Console.WriteLine("[{0}:{1}]/{2} gives [{3}:{4}] with {5} ticks of {6} units each.", low, high, tickCountGoal, picker.tickLow, picker.tickHigh, picker.tickCount, picker.tickUnit);
}
static void Main(string[] args)
{
testPicker(4.7, 39.2, 13);
testPicker(4.7, 39.2, 16);
testPicker(4.7, 39.2, 19);
testPicker(4.7, 39.2, 21);
testPicker(4.7, 39.2, 24);
testPicker(1967, 2011, 20);
testPicker(1967, 2011, 10);
testPicker(2.71, 3.14, 5);
testPicker(.0568, 13, 20);
}
}
}
I think you mean minNumber and not meanNumber.
The formula is close to what you say. Your range is maxNumber - minNumber. If you want some space on either side add 2k, where k is the space for either side. You know your graph is Y pixels wide. Y/range is how many pixels there are per unit for your graph.
You basically apply this adjustment while drawing the graph. Apply a shift based on your min, and then a strech based on your pixel/unit.
So Drawing point X means you are actually drawing at ((X - min) / pixels per unit).
I'm not 100% convinced that this is a programming question (although there are a decent handful of graphing libraries one could use), but the general idea would be this.
You have these points coming in, let's say -5. That's the 0th value we've received, so for an x value of 0, we place -5 on the y-axis. We repeat for -1, 4, etc.
So, you'd get a list looking something like this (figuratively):
X | Y
0 | -5
1 | -1
2 | 4
3 | 5
4 | 15
The result is a scatterplot (not a line), but there are tools in Excel to get that for you.
[EDIT] To get it as an actual function, you could use the following form:
y-y_1=m(x-x_1)
Where m = (y_2-y_1)/(x_2-x_1), y_2 is your highest y-value, y_1 is your lowest, x_2 is your highest x-value, and x_1 is your lowest.