2009-10-21 13 views
10

Mam niektóre dane z bazy danych (SQLite), mapowanie wartości (liczba całkowita) na datę. Data jest ciągiem o tym formacie: YYYY-MM-DD hh:mm. Daty nie są równomiernie rozłożone. Chcę narysować wykres liniowy z datami X i wartościami na Y. Jaki jest najłatwiejszy sposób na zrobienie tego w Perlu?Jak wykreślić wykres z szeregów czasowych w Perlu?

Próbowałem DBIx::Chart, ale nie mogłem rozpoznać moich dat. Próbowałem też GD::Graph, ale jak mówi dokumentacji:

GD :: Graph nie obsługuje oś liczbowa x drodze powinien. Dane dla osi X powinny być równomiernie rozmieszczone

Odpowiedz

8

Możesz prowadzić gnuplot używając Chart::Gnuplot.

Alternatywnie, jeśli SVG jest akceptowalnym formatem wyjściowym, istnieje SVG::TT::Graph.

+2

+1 do wykresu :: Gnuplot. To mój ulubiony moduł do tworzenia wykresów i najczystszy interfejs do gnuplot, który znalazłem, który nie zawiera w sobie surowych poleceń do niego. – brunov

+0

Udało mi się wykreślić moje dane za pomocą gnuplot, ustawiając poprawny format czasu, wydaje mi się, ale oś X rozciąga się od 1985 r. Do ponad roku 2010, podczas gdy wszystkie moje daty są w 2009 r. Nadal muszę znaleźć, jak mogę powiedzieć gnuplot, aby ustawić oś X tak, aby rozciągała się tylko od pierwszej daty do daty lasu. – Jazz

+0

@Jazz Możesz ustawić, które ticks są wyświetlane: http://search.cpan.org/perldoc/Chart::Gnuplot#xtics,_ytics,_ztics Możesz także ustawić zakresy http://search.cpan.org/perldoc/Chart :: Gnuplot # xrange, _yrange, _zrange –

3

Próbowałem DBIx :: Chart ale nie mogłem go rozpoznać moje dat.

Czy próbowałeś przetłumaczyć swoje daty na Unix-Timestamp i użyć ich jako dat X?

+0

Nie. Jaki jest lepszy sposób na konwersję moich dat? Jak mogę wyświetlić datę, a nie znaczniki czasu na osi X? – Jazz

+0

Nie sądzę, DBIx :: Chart obsługuje to. Możesz więc albo podklasyfikować go i dodać tę funkcjonalność, albo skorzystać z sugestii Sinana dla Chart :: Gnuplot, jestem w trakcie głosowania w górę. – DVK

+0

Zamiast porzucać DBIx :: Chart z powodu problemów z kodem ("Nie mogłem rozpoznać moich dat"), może warto napisać kod, który dawał ci problemy, a może moglibyśmy z Tobą debugować? Gdybyśmy zrezygnowali z rozwiązań, ponieważ nasza początkowa praca z nimi nie przyniosła oczekiwanych rezultatów, szybko wyczerpały się nam rozwiązania. –

2

Najłatwiejszym sposobem na zrobienie tego z Perlem jest użycie Perla do uruchomienia procesu Gnuplot. Możesz użyć set timefmt x "%Y-%m-%d" i automatycznie przeanalizuje dane w formacie, który posiadasz. Gnuplot obsługuje również wiele formatów wyjściowych.

+0

Chciałem uniknąć konieczności instalowania gnuplot, ale może lepiej to zrobić. – Jazz

+0

Nie wiem, czy lepiej go zainstalować, czy nie, ale każde rozwiązanie graficzne będzie wymagało zainstalowania czegoś, a przynajmniej gnuplot jest na tyle długi, że działa całkiem dobrze na większości systemów. –

1

Polecam znormalizować daty na liczbach całkowitych. Metoda brutalnej siły będzie oczywiście używać sekund epok, ale to może nie wyglądać zbyt ładnie na wykresie, więc normalizuj się przez liniową transformację do pewnego przyzwoitego zakresu (mogę podać szczegóły, jak chcesz).

11

Można użyć wykresu :: zatrzaskowe w osi :: 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'); 

trzeba konwertować razy do znaczników czasu Uniksa, ale DWIMs.

+1

DateTime :: Format :: DBI działa bardzo dobrze (który deleguje do właściwego modułu DateTime :: Format :: *) – jshirley

+1

Nie wiedziałem o Chart :: Clicker. Ale problem wyświetlania terminów przyjaznych człowiekowi wciąż pozostaje. – Jazz

+4

Oś :: DateTime automatycznie formatuje daty, używając formatu zależnego od zakresu. Jeśli nie podoba ci się jego wybór, możesz wywołać jego metodę 'format' z dowolnym łańcuchem formatowania akceptowanym przez' strftime 'DateTime i będzie to wykorzystywać. Możesz kontrolować liczbę i/lub pozycje znaczników, które będą wyświetlane za pomocą metod 'ticks' lub' tick_values' z Chart :: Clicker :: Axis. – hobbs

1

Potrzebujesz wykresu generowanego w czasie rzeczywistym lub jednorazowego raportu? Jeśli to drugie, to można użyć modułów DateTime do generowania wartości Excel i wykres je w programie Excel (lub jego odpowiednik open source.)

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

czas temu zrobiłem coś takiego za pomocą Asymptote. To niesamowity pakiet, ale nie jest łatwy w użyciu.

+0

Próbowałem już eksportu w formacie CSV, aby go narysować za pomocą OpenOffice.org Calc. Nie potrzebuję tego w czasie rzeczywistym, ale będę musiał generować kilka wykresów regularnie, przynajmniej raz dziennie, więc chciałbym uniknąć ręcznych operacji. – Jazz

3

To załatwiło sprawę dla mnie:

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

Poniższa nie będzie działać w SQLLite jako rekurencyjne zapytania nie są obsługiwane, ale to będzie działać w Oracle.

Można utworzyć stały szeregi czasowe dla Oracle dB z podkwerendzie jak ten:

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

następnie połączyć tę serię czasową do danych wykresu przy użyciu LEFT JOIN tak:

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; 

Powyższy przykład wyświetli ostatnie 60 minut i zadziała ** z DBIx :: Chart. Aby zmienić rozdzielczość na godziny, zmieniaj "MI" na "HH24" lub co 24 godziny, możesz wspólnie pominąć parametr formatu daty.

Aby zmienić zakres, po prostu ustaw wartość CONNECT BY LEVEL na liczbę punktów serii czasowych, które należy wykreślić w określonej rozdzielczości.

** Uwaga: DBIx :: Wykres będzie barfowany, jeśli wszystkie wartości punktów danych będą równe zero (tj. Niezdefiniowane). Nie mogę ci pomóc, przepraszam.

Powiązane problemy