Ответ 1
Вы можете управлять gnuplot с помощью Chart::Gnuplot.
В качестве альтернативы, если SVG является приемлемым форматом вывода, есть SVG::TT::Graph.
У меня есть некоторые данные из базы данных (SQLite), сопоставляющие значение (целое число) с датой. Дата - это строка с таким форматом: YYYY-MM-DD hh:mm
. Даты неравномерно распределены. Я хочу сделать линейный график с датами на 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, но это DWIMs.
Я попробовал DBIx:: Chart, но не смог распознать даты.
Вы пытались перевести свои даты на Unix-Timestamps и использовать их как даты 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 dBs с подзапросом, подобным этому:
(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 будет barf, если все значения datapoint равны нулю (т.е. undefined). Не могу вам помочь, извините.