11

我有一些来自数据库(SQLite)的数据,将一个值(一个整数)映射到一个日期。日期是具有以下格式的字符串:YYYY-MM-DD hh:mm. 日期分布不均匀。我想画一个带有日期X和值的折线图Y。使用 Perl 最简单的方法是什么?

我尝试了 DBIx::Chart但我无法让它识别我的日期。我也试过GD::Graph,但正如文档所说:

GD::Graph 不支持数字 x 轴。X 轴的数据应等间距

4

8 回答 8

11

您可以使用 Chart::Clicker 的 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');

您必须将时间转换为 Unix 时间戳,但它是 DWIM。

于 2009-10-21T19:47:58.210 回答
8

您可以使用Chart::Gnuplot驱动gnuplot

或者,如果 SVG 是可接受的输出格式,则有SVG::TT::Graph

于 2009-10-21T13:09:20.887 回答
3

我尝试了 DBIx::Chart 但我无法让它识别我的日期。

您是否尝试过将日期转换为 Unix 时间戳并将其用作 X 日期?

于 2009-10-21T12:44:04.957 回答
3

这对我有用:

my $ctx = $chart->get_context('default');
$ctx->domain_axis(
    Chart::Clicker::Axis::DateTime->new(
        position        => 'bottom',
        orientation     => 'horizontal',
        ticks           => 5 ,
        format          => "%Y-%m-%d"
    )
);
于 2011-02-25T20:38:21.457 回答
2

我发现使用 Perl 执行此操作的最简单方法是使用 Perl 运行 gnuplot 进程。您可以使用set timefmt x "%Y-%m-%d"它,它会自动以您拥有的格式解析数据。Gnuplot 还支持多种输出格式。

于 2009-10-21T12:46:49.580 回答
1

我建议将日期标准化为整数。蛮力方法当然是使用纪元秒,但这在图表上可能看起来不太好,所以通过线性变换归一化到一些合适的范围(如果你愿意,我可以提供详细信息)。

于 2009-10-21T12:47:23.657 回答
1

您是否需要实时生成图表,还是需要一次性报告?如果是后者,那么您可以使用 DateTime 模块生成 Excel 值并在 Excel(或其开源对应物)中绘制它们。

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";

前段时间我使用Asymptote做了类似的事情。这是一个令人难以置信的软件包,但它并不容易使用。

于 2009-10-21T20:20:06.217 回答
1

由于不支持递归查询,因此以下内容在 SQLLite 中不起作用,但在 Oracle 中将起作用。

您可以使用如下子查询为 Oracle dB 创建一个连续的时间序列:

(SELECT   TRUNC (SYSDATE - x / 1440, 'MI') ts
             FROM   (SELECT       LEVEL x
                           FROM   DUAL
                     CONNECT BY   LEVEL <= 60))

然后使用这样的 LEFT JOIN 将该时间序列链接到您的图表数据:

    SELECT   TO_CHAR (A.TS, 'DD/MM/YYYY HH24:MI') TS
        , b.DATAPOINT1, b.DATAPOINT2
   FROM   (SELECT   TRUNC (SYSDATE - x / 1440, 'MI') ts
             FROM   (SELECT       LEVEL x
                           FROM   DUAL
                     CONNECT BY   LEVEL <= 60)) a
        , MY_CHART_DATA b
  WHERE   a.ts = b.ts(+) ORDER BY   a.TS;

上面的示例将绘制最后 60 分钟,并将与 DBIx::Chart 一起工作**。要将分辨率更改为小时,请将“MI”更改为“HH24”,或者每 24 小时一次,您可以一起省略日期格式参数。

要更改范围,只需将 CONNECT BY LEVEL 值设置为您需要以指定分辨率绘制的时间序列点数。

**注意:如果所有数据点值都为零(即未定义),则 DBIx::Chart 将失败。帮不了你,对不起。

于 2013-02-01T21:26:15.540 回答