Как я могу построить график временных рядов с Perl?

StackOverflow https://stackoverflow.com/questions/1600551

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня есть некоторые данные из базы данных (SQLite), отображающие значение (целое число) на дату. Дата - это строка в следующем формате: ГГГГ-ММ-ДД чч: мм . Даты распределены неравномерно. Я хочу нарисовать линейный график с датами в X и значениями в Y . Какой самый простой способ сделать это с Perl?

Я пытался DBIx :: Chart , но не смог заставить его распознать мои даты , Я также попробовал GD :: Graph , но, как сказано в документации:

  

GD :: Graph не поддерживает числовой x   Ось так, как должно. Данные для X   оси должны быть на одинаковом расстоянии

Это было полезно?

Решение

Вы можете управлять gnuplot , используя Chart :: Gnuplot .

В качестве альтернативы, если SVG является приемлемым выходным форматом, существует SVG :: TT :: Graph .

Другие советы

Вы можете использовать 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.

  

Я попробовал DBIx :: Chart, но не смог распознать мои даты.

Вы пытались перевести свои даты в метки времени Unix и использовать их как даты X?

Это помогло мне:

my $ctx = $chart->get_context('default');
$ctx->domain_axis(
    Chart::Clicker::Axis::DateTime->new(
        position        => 'bottom',
        orientation     => 'horizontal',
        ticks           => 5 ,
        format          => "%Y-%m-%d"
    )
);

Я нашел самый простой способ сделать это с помощью Perl - использовать Perl для запуска процесса gnuplot. Вы можете использовать set timefmt x "% Y-% m-% d " , и он автоматически проанализирует данные в имеющемся формате. Gnuplot также поддерживает множество выходных форматов.

Я бы порекомендовал нормализовать даты в целые числа. Методом грубой силы будет, конечно, использование секунд эпохи, но это может показаться не слишком хорошим на графике, поэтому нормализуйте его путем линейного преобразования в некоторый приличный диапазон (я могу предоставить подробности того, как, если хотите).

Вам нужен график для создания в реальном времени или для одноразового отчета? Если последнее, то вы можете использовать модули 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 . Это невероятный пакет, но его нелегко использовать.

Следующее не будет работать в SQLLite, поскольку рекурсивные запросы не поддерживаются, но это будет работать в Oracle.

Вы можете создать непрерывный временной ряд для дБ Oracle с помощью такого подзапроса:

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

Затем свяжите этот временной ряд с данными диаграммы, используя левое соединение следующим образом:

    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 прекратит работу, если все значения точек данных равны нулю (т.е. не определены). Не могу вам помочь, извините.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top