tags:

views:

1171

answers:

7

I have some data from a database (SQLite), mapping a value (an integer) to a date. A date is a string with this format: YYYY-MM-DD hh:mm. The dates are not uniformly distributed. I want do draw a line graph with the dates on X and the values on Y. What is the easiest way to do this with Perl?

I tried DBIx::Chart but I could not make it recognize my dates. I also tried GD::Graph, but as the documentation says:

GD::Graph does not support numerical x axis the way it should. Data for X axes should be equally spaced

+2  A: 

I tried DBIx::Chart but I could not make it recognize my dates.

Have you tried to translate your dates to Unix-Timestamps and use them as X dates?

Martin Hohenberg
No. What is the better way to convert my dates? Then how can I view the date and not the timestamps on the x axis?
Jazz
I don't think DBIx::Chart supports that. So you can either sub-class it and add this functionality, or go with Sinan's suggestion for Chart::Gnuplot, I'm up-voting that.
DVK
+2  A: 

The easiest way I've found to do this with Perl is to use the Perl to run a gnuplot process. You can use set timefmt x "%Y-%m-%d" and it will automatically parse the data in the format you have. Gnuplot also supports a variety of output formats.

Kinopiko
I wanted to avoid having to install gnuplot, but maybe it is the better thing to do.
Jazz
I don't know if it is better to install it or not, but any graphics solution will require you to install something, and at least gnuplot has been around long enough that it works pretty well on most systems.
Kinopiko
+1  A: 

I would recommend normalizing the dates to integers. The brute force way would be of course using epoch seconds, but that might not look too nice on a graph, so normalize by a linear transform into some decent range (I can provide details of how if you wish).

DVK
+6  A: 

You can drive gnuplot using Chart::Gnuplot.

Alternatively, if SVG is an acceptable output format, there is SVG::TT::Graph.

Sinan Ünür
+1 to Chart::Gnuplot. It's my favourite charting module, and the sanest interface to gnuplot that I found that doesn't involve piping raw commands to it.
brunov
I did manage to plot my data with gnuplot, setting the correct time format, it seems nice but the X axis extends from 1985 to more than 2010, whereas my dates all are in 2009. I still need to find how I can say to gnuplot to set the X axis to extend only from the first date to the las date.
Jazz
@Jazz You can set which ticks are displayed: http://search.cpan.org/perldoc/Chart::Gnuplot#xtics,_ytics,_ztics You can also set the ranges http://search.cpan.org/perldoc/Chart::Gnuplot#xrange,_yrange,_zrange
Sinan Ünür
@Sinan I already found that, I was hoping for automatic ranges.
Jazz
In fact I was misusing Gnuplot. With the Chart::Gnuplot::DataSet option timefmt => '%Y-%m-%d %H:%M', and the Chart::Gnuplot option timeaxis => "x", it works perfectly!
Jazz
+6  A: 

You can use Chart::Clicker's Axis::DateTime:

#!/usr/local/bin/perl -w
use strict;
use Chart::Clicker;
use Chart::Clicker::Axis::DateTime;
use Chart::Clicker::Data::Series;
use Chart::Clicker::Data::DataSet;
use Chart::Clicker::Renderer::Point;

my $cc = Chart::Clicker->new;
my $series = Chart::Clicker::Data::Series->new(
    values    => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
    keys      => [
        1256147117, 1256148117, 1256149117, 1256150117, 1256151117, 1256152117,
        1256153117, 1256154117, 1256155117, 1256156117
    ],
);
my $ctx = $cc->get_context('default');
$ctx->domain_axis(Chart::Clicker::Axis::DateTime->new(position => 'bottom', orientation     => 'horizontal'));
my $ds = Chart::Clicker::Data::DataSet->new(series => [ $series ]);
$cc->add_to_datasets($ds);
$cc->write_output('foo.png');

You have to convert your times into Unix timestamps, but it DWIMs.

gphat
DateTime::Format::DBI works very well (which delegates to the proper DateTime::Format::* module)
I did not know about Chart::Clicker. But the problem of displaying human friendly dates still remains.
Jazz
Axis::DateTime formats the dates automatically, using a format that depends on the range. If you don't like its choice, you can call its `format` method with any formatting string acceptable to DateTime's `strftime` and it will use that. You can control the number and/or positions of tickmarks to show with the `ticks` or `tick_values` methods from Chart::Clicker::Axis.
hobbs
Chart::Clicker seems great, but unfortunately, I'm using ActivePerl 5.10 on Win32, and Chart::Clicker seems unavailable as a PPM package.
Jazz
A: 

Do you need your graph to be generated in real time, or is for a one-off report? If the latter, then you can use DateTime modules to generate Excel values and graph them in Excel (or its open-source counterpart.)

use DateTime::Format::MySQL;
use DateTime::Format::Excel;

my $dt = DateTime::Format::MySQL->parse_datetime( '2003-01-16 23:12:01' );
print $dt, "\n";
my $daynum = DateTime::Format::Excel->format_datetime($dt);
print $daynum, "\n";

Time ago I did something like this using Asymptote. It is an incredible package, but it's not easy to use.

Leonardo Herrera
I already tried a CSV export to plot it with OpenOffice.org Calc. I don't need it in real time, but I will have to generate several graphes regularly, at least one time per day, so I would like to avoid manual operations.
Jazz
A: 

Hi, I want to include date in X axes. I have that :

@hours = (
1272672000, 1272758400, 1272844800, 1272931200, 1273017600, 1273104000, 1273208400, 1273294800
);
@bw1 = (
$d1, $d2, $d3, $d4, $d5, $d6, $d7, $d8
);


my $series = Chart::Clicker::Data::Series->new(
    keys => \@hours,
    values => \@bw1,

But on my graphics I don't have the date, but just the day(1,2,3..) How can i have something that 2010-05-12 09:21:21 on my axes X. Thank for your answers. And sorry for my bad english i'm french. Thomas

Thomas