0

I am having an issue with some of my (hundreds) of variables with mostly annual values having data only for certain years. So, instead of 1990,1992,1992,.... they have 1990,2000,2005,2010 ... or 1990,1995,2000,2005,2008

The resulting chart shows then for the same distance between all years, although, in the case of 1990,2000,2005,2010 the distance between 1990 and 2000 is (two times) larger than between the following years. Here is an example.

Now, I haven't seen any Highcharts internal solution to this. Would have been nice to have a parameter to be specified like "distribute years correctly on x-axis". I guess that doesn't exist.

Which means I would need to code something in PHP. Some sort of "injection" into the two arrays (x-axis, y-axis) which would fill the x-axis-array with the missing years and the y-axis-array with NULL values.

Thanks for any hints!

luftikus143
  • 1,285
  • 3
  • 27
  • 52
  • In case when you use categories, you need to add null elements to have distance between them, when you would like to have irrerugalr tick, you need to use datetime type of xAxis and set ordinal as false. – Sebastian Bochan Jan 30 '14 at 10:11
  • Thx! If I see it correctly from for example [here](http://stackoverflow.com/questions/18107525/highcharts-datetime-xaxis-without-missing-values-weekends) ordinal is not available in Highcarts, but only in Highstocks. Right so? – luftikus143 Jan 30 '14 at 10:24
  • Excatly, you are right. – Sebastian Bochan Jan 30 '14 at 11:05

3 Answers3

0

You can fix it in PHP as you guessed. here is how i did it:

while($row = mysql_fetch_assoc($result,1))
{
    $chartData[$row['date']] = $row['value']; 
    $chartDataDates[$row['date']] = 1;
}
$max_date = max( array_keys( $chartDataDates) );
$min_date = min( array_keys( $chartDataDates) );
for($i=$min_date;$i<$max_date;$i++)
{
    $chartDataDates[$i] = 1;
}
foreach($chartDataDates as $date=>$value)
{
    if(!isset($chartData[$date]))
    $chartData[$date] = 0;
}

and in highcharts parameters:

        xAxis: {categories: ['<?php echo implode("','",array_keys($chartDataDates)); ?>']},
        series: [<?php 
            name: 'my data',
            data: [<?php echo implode(",",$chartData ) ?>]
        }
Volkan Ulukut
  • 4,230
  • 1
  • 20
  • 38
0

Thanks for the hints!

I finally went with a probably bit more complex solution, checking first the need for additional computation if something like this happens.

// categories = years
$cat = "";

for ($j = 0; $j < count($data_x); $j++)
{
    $cat .= "'" . $data_x[$j] . "',";

    // what happens with data like "1990,2000,2005,2008" (id=2199)
    if (($j >= 1) && ($j < (count($data_x) - 1)))
    {
        if (!(($data_x[($j)] - $data_x[($j - 1)]) == ($data_x[($j + 1)] - $data_x[$j])))
        {
            // what to do here?
            $flag_years = true;
        }
    }
}

$cat = substr($cat, 0, -1);

And if so, recalculating the years:

// if need to display additional years due to "1990,2000,2005,2008"
if ($flag_years)
{
    $data_x_new = array();

    $min_date = min($data_x);
    $max_date = max($data_x);

    for ($i = $min_date; $i <= $max_date; $i++)
    {
        $data_x_new[($i - $min_date)] = $i;
    }

    $cat = "'" . implode("','", $data_x_new) . "'";

    $numYears = count($data_x_new);
}

And then taking care of additional NULL values to be inserted in $data_y:

// loop through countries
for ($i = 0; $i < $numCountries; $i++)
{   
    $val = "[";
    $count = 0;

    // loop through values
    for ($j = 0; $j < $numYears; $j++)
    {
        // if need to display additional years due to "1990,2000,2005,2008"
        if ($flag_years)
        {
            if ($data_x_new[$j] == $data_x[($j - $count)])
            {
                $val .= $data_y[$i][($j - $count)] . ",";
            }
            else
            {
                $val .= "null,";
                $count++;
            }
        }
        // otherwise normal display
        else
        {
            if ($data_y[$i][$j] == "")
            {
                $val .= "null,";
            }
            else
            {
                $val .= $data_y[$i][$j] . ",";
            }
        }
    }

    $val = substr($val, 0, -1) . "]";


    // store all in an array        
    $vals[$i] = $val;
}

Guess there is an easier solution to this, but, hey, it works!

luftikus143
  • 1,285
  • 3
  • 27
  • 52
  • I think this is WAY too complex a solution for the problem at hand, if I understand the problem correctly. See my answer. – jlbriggs Jan 31 '14 at 14:58
0

All you have to do in Highcharts to have years distributed 'correctly' is to use a datetime axis type, and specify an actual date within that year as the x value

I usually use January 1st, but it doesn't matter which date, as long as it's the same date for each year.

Then you just format your labels to display the date as the year only.

No loops or calculations required.

{{EDIT:

updated fiddle example: http://jsfiddle.net/jlbriggs/6H3jL/2/

Also, if you want to only have x axis labels where there is a data point, you can use the tickPositions property, and provide it with an array of the same datetime values you send as the x values for your data

jlbriggs
  • 17,612
  • 4
  • 35
  • 56
  • Thanks for this. But I don't see how to achieve what I need with these commands. I put up a [fiddle here](http://jsfiddle.net/luftikus143/6H3jL); perhaps you can check it out and correct accordingly? – luftikus143 Feb 03 '14 at 06:19
  • 1) get rid of the categories. Categories and datetime axes are mutually exclusive. 2) get rid of the label step setting. 3) you need to send a datetime value as your x value for each data point, so the chart knows where to put it. See updated example: http://jsfiddle.net/jlbriggs/6H3jL/2/ – jlbriggs Feb 03 '14 at 14:00