2009-10-21 47 views
10

Tôi có một số dữ liệu từ một cơ sở dữ liệu (SQLite), ánh xạ một giá trị (một số nguyên) cho một ngày. Ngày là một chuỗi có định dạng này: YYYY-MM-DD hh:mm. Các ngày không được phân phối thống nhất. Tôi muốn vẽ biểu đồ đường với các ngày trên X và các giá trị trên Y. Cách dễ nhất để làm điều này với Perl là gì?Làm thế nào tôi có thể vẽ đồ thị chuỗi thời gian với Perl?

Tôi đã thử DBIx::Chart nhưng tôi không thể làm cho nó nhận ra ngày của tôi. Tôi cũng đã cố gắng GD::Graph, nhưng như các tài liệu nói:

GD :: Graph không hỗ trợ số x trục đường nó cần. Dữ liệu cho X trục nên được đặt cách nhau không kém

Trả lời

8

Bạn có thể lái xe gnuplot sử dụng Chart::Gnuplot.

Hoặc, nếu SVG là định dạng đầu ra có thể chấp nhận, có SVG::TT::Graph.

+2

+1 vào biểu đồ :: Gnuplot. Đó là mô-đun biểu đồ yêu thích của tôi và giao diện trực tuyến nhất với gnuplot mà tôi thấy không liên quan đến các lệnh thô đến đường ống. – brunov

+0

Tôi đã quản lý để vẽ dữ liệu của tôi với gnuplot, thiết lập định dạng thời gian chính xác, nó có vẻ tốt đẹp nhưng trục X kéo dài từ năm 1985 đến hơn năm 2010, trong khi tất cả các ngày của tôi là vào năm 2009. Tôi vẫn cần phải tìm cách tôi có thể nói gnuplot để đặt trục X chỉ mở rộng từ ngày đầu tiên đến ngày las. – Jazz

+0

@Jazz Bạn có thể thiết lập những ve được hiển thị: http://search.cpan.org/perldoc/Chart::Gnuplot#xtics,_ytics,_ztics Bạn cũng có thể thiết lập các phạm vi http://search.cpan.org/perldoc/Biểu đồ :: Gnuplot # xrange, _yrange, _zrange –

3

tôi đã cố gắng DBIx :: Chart nhưng tôi không thể làm cho nó nhận ra số ngày của tôi.

Bạn đã thử dịch ngày của mình sang Unix-Timestamps và sử dụng chúng làm ngày X không?

+0

No. Cách nào tốt hơn để chuyển đổi ngày của tôi? Sau đó làm thế nào tôi có thể xem ngày và không phải là dấu thời gian trên trục x? – Jazz

+0

Tôi không nghĩ rằng DBIx :: Chart hỗ trợ điều đó. Vì vậy, bạn có thể hoặc là sub-class nó và thêm chức năng này, hoặc đi với lời đề nghị của Sinan cho Chart :: Gnuplot, tôi đang bỏ phiếu đó. – DVK

+0

Thay vì bỏ DBIx :: Biểu đồ vì một số vấn đề trong mã của bạn ("Tôi không thể làm cho nó nhận ra ngày của tôi"), tại sao không đăng mã đã cho bạn vấn đề và có lẽ chúng tôi có thể gỡ lỗi nó với bạn? Nếu chúng tôi từ bỏ các giải pháp vì công việc ban đầu của chúng tôi với họ đã không thể hiện ra cách chúng tôi muốn, chúng tôi sẽ hết các giải pháp một cách nhanh chóng. –

2

Cách dễ nhất tôi đã tìm thấy để làm điều này với Perl là sử dụng Perl để chạy quy trình gnuplot. Bạn có thể sử dụng set timefmt x "%Y-%m-%d" và nó sẽ tự động phân tích dữ liệu theo định dạng bạn có. Gnuplot cũng hỗ trợ nhiều định dạng đầu ra khác nhau.

+0

Tôi muốn tránh phải cài đặt gnuplot, nhưng có lẽ đó là điều tốt hơn để làm. – Jazz

+0

Tôi không biết có nên cài đặt hay không, nhưng bất kỳ giải pháp đồ họa nào cũng sẽ yêu cầu bạn cài đặt thứ gì đó và ít nhất gnuplot đã đủ dài để hoạt động khá tốt trên hầu hết các hệ thống. –

1

Tôi khuyên bạn nên chuẩn hóa ngày thành số nguyên. Cách bạo lực sẽ là tất nhiên bằng cách sử dụng giây epoch, nhưng điều đó có thể không nhìn quá đẹp trên một đồ thị, vì vậy bình thường hóa bởi một biến đổi tuyến tính vào một số phạm vi phong nha (tôi có thể cung cấp chi tiết như thế nào nếu bạn muốn).

11

Bạn có thể sử dụng Chart :: Clicker của 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'); 

Bạn cần phải chuyển đổi thời gian của bạn vào timestamps Unix, nhưng nó DWIMs.

+1

DateTime :: Định dạng :: DBI hoạt động rất tốt (mà đại biểu cho đúng DateTime :: Format :: * module) – jshirley

+1

Tôi không biết về Chart :: Clicker. Nhưng vấn đề hiển thị ngày thân thiện với con người vẫn còn. – Jazz

+4

Trục :: Ngày giờ định dạng ngày tự động, sử dụng định dạng phụ thuộc vào phạm vi. Nếu bạn không thích sự lựa chọn của nó, bạn có thể gọi phương thức 'format' của nó với bất kỳ chuỗi định dạng nào được chấp nhận cho' strftime' của DateTime và nó sẽ sử dụng nó. Bạn có thể kiểm soát số lượng và/hoặc vị trí của dấu chọn để hiển thị với các phương thức 'ticks' hoặc' tick_values' từ Chart :: Clicker :: Axis. – hobbs

1

Bạn có cần đồ thị của mình được tạo trong thời gian thực hay cho báo cáo một lần không? Nếu sau này, sau đó bạn có thể sử dụng module DateTime để tạo ra giá trị Excel và vẽ đồ thị chúng trong Excel (hoặc đối tác mã nguồn mở của nó.)

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

Thời gian trước, tôi đã làm một cái gì đó như thế này sử dụng Asymptote. Nó là một gói đáng kinh ngạc, nhưng nó không dễ sử dụng.

+0

Tôi đã thử xuất CSV để vẽ nó bằng OpenOffice.org Calc. Tôi không cần nó trong thời gian thực, nhưng tôi sẽ phải tạo ra một số đồ thị thường xuyên, ít nhất một lần mỗi ngày, vì vậy tôi muốn tránh các hoạt động thủ công. – Jazz

3

này đã làm các trick cho tôi:

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

Sau đây sẽ không làm việc trong SQLLite như các truy vấn đệ quy không được hỗ trợ, nhưng nó sẽ làm việc trong Oracle.

Bạn có thể tạo một chuỗi thời gian liên tục cho Oracle DBS với một subquery như thế này:

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

Sau đó, liên kết mà chuỗi thời gian để biểu đồ dữ liệu của bạn bằng cách sử dụng LEFT JOIN như thế này:

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; 

Ví dụ trên sẽ vẽ 60 phút cuối cùng và sẽ hoạt động ** với DBIx :: Biểu đồ. Để thay đổi độ phân giải thành giờ thay đổi 'MI' thành 'HH24', hoặc cứ sau 24 giờ bạn có thể bỏ qua tất cả tham số định dạng ngày.

Để thay đổi phạm vi, chỉ cần đặt giá trị CONNECT BY LEVEL thành số chuỗi thời gian bạn cần vẽ theo độ phân giải đã chỉ định của mình.

** Lưu ý: DBIx :: Biểu đồ sẽ chặn nếu tất cả giá trị datapoint là số không (ví dụ: không xác định). Không thể giúp bạn ở đó, xin lỗi.

Các vấn đề liên quan