File Coverage

blib/lib/PDL/Stats/TS.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             #
2             # GENERATED WITH PDL::PP from lib/PDL/Stats/TS.pd! Don't modify!
3             #
4             package PDL::Stats::TS;
5              
6             our @EXPORT_OK = qw(acf acvf dseason fill_ma filter_exp filter_ma mae mape wmape portmanteau pred_ar );
7             our %EXPORT_TAGS = (Func=>\@EXPORT_OK);
8              
9 1     1   250682 use PDL::Core;
  1         3  
  1         8  
10 1     1   523 use PDL::Exporter;
  1         11  
  1         10  
11 1     1   31 use DynaLoader;
  1         2  
  1         533  
12              
13              
14            
15             our @ISA = ( 'PDL::Exporter','DynaLoader' );
16             push @PDL::Core::PP, __PACKAGE__;
17             bootstrap PDL::Stats::TS ;
18              
19              
20              
21              
22              
23              
24              
25              
26             #line 6 "lib/PDL/Stats/TS.pd"
27              
28             =encoding utf8
29              
30             =head1 NAME
31              
32             PDL::Stats::TS -- basic time series functions
33              
34             =head1 DESCRIPTION
35              
36             The terms FUNCTIONS and METHODS are arbitrarily used to refer to
37             methods that are threadable and methods that are NOT threadable,
38             respectively. Plots require L.
39              
40             ***EXPERIMENTAL!*** In particular, bad value support is spotty and may be shaky. USE WITH DISCRETION!
41              
42             =head1 SYNOPSIS
43              
44             use PDL::LiteF;
45             use PDL::Stats::TS;
46              
47             my $r = $data->acf(5);
48              
49             =cut
50              
51             use strict;
52             use warnings;
53             use Carp;
54             use PDL::LiteF;
55             use PDL::Stats::Basic;
56             use PDL::Stats::Kmeans;
57             #line 58 "lib/PDL/Stats/TS.pm"
58              
59              
60             =head1 FUNCTIONS
61              
62             =cut
63              
64              
65              
66              
67              
68              
69             =head2 acf
70              
71             =for sig
72              
73             Signature: (x(t); [o]r(h); IV lag=>h)
74             Types: (float double)
75              
76             =for usage
77              
78             $r = acf($x, $lag);
79             acf($x, $r, $lag); # all arguments given
80             $r = $x->acf($lag); # method call
81             $x->acf($r, $lag);
82              
83             =for ref
84              
85             Autocorrelation function for up to lag h. If h is not specified it's set to t-1 by default.
86              
87             acf does not process bad values.
88              
89             =for example
90              
91             usage:
92              
93             pdl> $a = sequence 10
94              
95             # lags 0 .. 5
96              
97             pdl> p $a->acf(5)
98             [1 0.7 0.41212121 0.14848485 -0.078787879 -0.25757576]
99              
100             =pod
101              
102             Broadcasts over its inputs.
103              
104             =for bad
105              
106             C does not process bad values.
107             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
108              
109             =cut
110              
111              
112              
113              
114              
115             #line 79 "lib/PDL/Stats/TS.pd"
116             sub PDL::acf {
117             my ($self, $h) = @_;
118             $h ||= $self->dim(0) - 1;
119             PDL::_acf_int($self, my $r = PDL->null, $h+1);
120             $r;
121             }
122             #line 123 "lib/PDL/Stats/TS.pm"
123              
124             *acf = \&PDL::acf;
125              
126              
127              
128              
129              
130              
131             =head2 acvf
132              
133             =for sig
134              
135             Signature: (x(t); [o]v(h); IV lag=>h)
136             Types: (float double)
137              
138             =for usage
139              
140             $v = acvf($x, $lag);
141             acvf($x, $v, $lag); # all arguments given
142             $v = $x->acvf($lag); # method call
143             $x->acvf($v, $lag);
144              
145             =for ref
146              
147             Autocovariance function for up to lag h. If h is not specified it's set to t-1 by default.
148              
149             acvf does not process bad values.
150              
151             =for example
152              
153             usage:
154              
155             pdl> $a = sequence 10
156              
157             # lags 0 .. 5
158              
159             pdl> p $a->acvf(5)
160             [82.5 57.75 34 12.25 -6.5 -21.25]
161              
162             # autocorrelation
163              
164             pdl> p $a->acvf(5) / $a->acvf(0)
165             [1 0.7 0.41212121 0.14848485 -0.078787879 -0.25757576]
166              
167             =pod
168              
169             Broadcasts over its inputs.
170              
171             =for bad
172              
173             C does not process bad values.
174             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
175              
176             =cut
177              
178              
179              
180              
181              
182             #line 134 "lib/PDL/Stats/TS.pd"
183             sub PDL::acvf {
184             my ($self, $h) = @_;
185             $h ||= $self->dim(0) - 1;
186             PDL::_acvf_int($self, my $v = PDL->null, $h+1);
187             $v;
188             }
189             #line 190 "lib/PDL/Stats/TS.pm"
190              
191             *acvf = \&PDL::acvf;
192              
193              
194              
195              
196              
197              
198             =head2 dseason
199              
200             =for sig
201              
202             Signature: (x(t); indx d(); [o]xd(t))
203             Types: (float double)
204              
205             =for usage
206              
207             $xd = dseason($x, $d);
208             dseason($x, $d, $xd); # all arguments given
209             $xd = $x->dseason($d); # method call
210             $x->dseason($d, $xd);
211              
212             =for ref
213              
214             Deseasonalize data using moving average filter the size of period d.
215              
216             =pod
217              
218             Broadcasts over its inputs.
219              
220             =for bad
221              
222             C processes bad values.
223             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
224              
225             =cut
226              
227              
228              
229              
230             *dseason = \&PDL::dseason;
231              
232              
233              
234              
235              
236              
237             =head2 fill_ma
238              
239             =for sig
240              
241             Signature: (x(t); indx q(); [o]xf(t))
242             Types: (float double)
243              
244             =for usage
245              
246             $xf = fill_ma($x, $q);
247             fill_ma($x, $q, $xf); # all arguments given
248             $xf = $x->fill_ma($q); # method call
249             $x->fill_ma($q, $xf);
250              
251             =for ref
252              
253             Fill missing value with moving average. xf(t) = sum(x(t-q .. t-1, t+1 .. t+q)) / 2q.
254              
255             =for bad
256              
257             fill_ma does handle bad values. Output pdl bad flag is cleared unless the specified window size q is too small and there are still bad values.
258              
259             =pod
260              
261             Broadcasts over its inputs.
262              
263             =for bad
264              
265             C processes bad values.
266             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
267              
268             =cut
269              
270              
271              
272              
273              
274             #line 251 "lib/PDL/Stats/TS.pd"
275             sub PDL::fill_ma {
276             my ($x, $q) = @_;
277             PDL::_fill_ma_int($x, $q, my $x_filled = PDL->null);
278             $x_filled->check_badflag;
279             # carp "ma window too small, still has bad value"
280             # if $x_filled->badflag;
281             return $x_filled;
282             }
283             #line 284 "lib/PDL/Stats/TS.pm"
284              
285             *fill_ma = \&PDL::fill_ma;
286              
287              
288              
289              
290              
291              
292             =head2 filter_exp
293              
294             =for sig
295              
296             Signature: (x(t); a(); [o]xf(t))
297             Types: (float double)
298              
299             =for usage
300              
301             $xf = filter_exp($x, $a);
302             filter_exp($x, $a, $xf); # all arguments given
303             $xf = $x->filter_exp($a); # method call
304             $x->filter_exp($a, $xf);
305              
306             =for ref
307              
308             Filter, exponential smoothing. xf(t) = a * x(t) + (1-a) * xf(t-1)
309              
310             =pod
311              
312             Broadcasts over its inputs.
313              
314             =for bad
315              
316             C does not process bad values.
317             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
318              
319             =cut
320              
321              
322              
323              
324             *filter_exp = \&PDL::filter_exp;
325              
326              
327              
328              
329              
330              
331             =head2 filter_ma
332              
333             =for sig
334              
335             Signature: (x(t); indx q(); [o]xf(t))
336             Types: (float double)
337              
338             =for usage
339              
340             $xf = filter_ma($x, $q);
341             filter_ma($x, $q, $xf); # all arguments given
342             $xf = $x->filter_ma($q); # method call
343             $x->filter_ma($q, $xf);
344              
345             =for ref
346              
347             Filter, moving average. xf(t) = sum(x(t-q .. t+q)) / (2q + 1)
348              
349             =pod
350              
351             Broadcasts over its inputs.
352              
353             =for bad
354              
355             C does not process bad values.
356             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
357              
358             =cut
359              
360              
361              
362              
363             *filter_ma = \&PDL::filter_ma;
364              
365              
366              
367              
368              
369              
370             =head2 mae
371              
372             =for sig
373              
374             Signature: (a(n); b(n); [o]c())
375             Types: (float double)
376              
377             =for usage
378              
379             $c = mae($a, $b);
380             mae($a, $b, $c); # all arguments given
381             $c = $a->mae($b); # method call
382             $a->mae($b, $c);
383              
384             =for ref
385              
386             Mean absolute error. MAE = 1/n * sum( abs(y - y_pred) )
387              
388             =pod
389              
390             Broadcasts over its inputs.
391              
392             =for bad
393              
394             C processes bad values.
395             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
396              
397             =cut
398              
399              
400              
401              
402             *mae = \&PDL::mae;
403              
404              
405              
406              
407              
408              
409             =head2 mape
410              
411             =for sig
412              
413             Signature: (a(n); b(n); [o]c())
414             Types: (float double)
415              
416             =for usage
417              
418             $c = mape($a, $b);
419             mape($a, $b, $c); # all arguments given
420             $c = $a->mape($b); # method call
421             $a->mape($b, $c);
422              
423             =for ref
424              
425             Mean absolute percent error. MAPE = 1/n * sum(abs((y - y_pred) / y))
426              
427             =pod
428              
429             Broadcasts over its inputs.
430              
431             =for bad
432              
433             C processes bad values.
434             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
435              
436             =cut
437              
438              
439              
440              
441             *mape = \&PDL::mape;
442              
443              
444              
445              
446              
447              
448             =head2 wmape
449              
450             =for sig
451              
452             Signature: (a(n); b(n); [o]c())
453             Types: (float double)
454              
455             =for usage
456              
457             $c = wmape($a, $b);
458             wmape($a, $b, $c); # all arguments given
459             $c = $a->wmape($b); # method call
460             $a->wmape($b, $c);
461              
462             =for ref
463              
464             Weighted mean absolute percent error. avg(abs(error)) / avg(abs(data)). Much more robust compared to mape with division by zero error (cf. Schütz, W., & Kolassa, 2006).
465              
466             =pod
467              
468             Broadcasts over its inputs.
469              
470             =for bad
471              
472             C processes bad values.
473             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
474              
475             =cut
476              
477              
478              
479              
480             *wmape = \&PDL::wmape;
481              
482              
483              
484              
485              
486              
487             =head2 portmanteau
488              
489             =for sig
490              
491             Signature: (r(h); longlong t(); [o]Q())
492             Types: (float double)
493              
494             =for usage
495              
496             $Q = portmanteau($r, $t);
497             portmanteau($r, $t, $Q); # all arguments given
498             $Q = $r->portmanteau($t); # method call
499             $r->portmanteau($t, $Q);
500              
501             =for ref
502              
503             Portmanteau significance test (Ljung-Box) for autocorrelations.
504              
505             =for example
506              
507             Usage:
508              
509             pdl> $a = sequence 10
510              
511             # acf for lags 0-5
512             # lag 0 excluded from portmanteau
513              
514             pdl> p $chisq = $a->acf(5)->portmanteau( $a->nelem )
515             11.1753902662994
516              
517             # get p-value from chisq distr
518              
519             pdl> use PDL::GSL::CDF
520             pdl> p 1 - gsl_cdf_chisq_P( $chisq, 5 )
521             0.0480112934306748
522            
523              
524             =pod
525              
526             Broadcasts over its inputs.
527              
528             =for bad
529              
530             C does not process bad values.
531             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
532              
533             =cut
534              
535              
536              
537              
538             *portmanteau = \&PDL::portmanteau;
539              
540              
541              
542              
543              
544              
545             =head2 pred_ar
546              
547             =for sig
548              
549             Signature: (x(p); b(p); [o]pred(t); IV end=>t)
550             Types: (float double)
551              
552             =for usage
553              
554             $pred = pred_ar($x, $b, $end);
555             pred_ar($x, $b, $pred, $end); # all arguments given
556             $pred = $x->pred_ar($b, $end); # method call
557             $x->pred_ar($b, $pred, $end);
558              
559             =for ref
560              
561             Calculates predicted values up to period t (extend current series up to period t) for autoregressive series, with or without constant. If there is constant, it is the last element in b, as would be returned by ols or ols_t.
562              
563             pred_ar does not process bad values.
564              
565             =for options
566              
567             CONST => 1,
568              
569             =for example
570              
571             Usage:
572              
573             pdl> $x = sequence 2
574              
575             # last element is constant
576             pdl> $b = pdl(.8, -.2, .3)
577              
578             pdl> p $x->pred_ar($b, 7)
579             [0 1 1.1 0.74 0.492 0.3656 0.31408]
580              
581             # no constant
582             pdl> p $x->pred_ar($b(0:1), 7, {const=>0})
583             [0 1 0.8 0.44 0.192 0.0656 0.01408]
584              
585             =pod
586              
587             Broadcasts over its inputs.
588              
589             =for bad
590              
591             C does not process bad values.
592             It will set the bad-value flag of all output ndarrays if the flag is set for any of the input ndarrays.
593              
594             =cut
595              
596              
597              
598              
599              
600             #line 425 "lib/PDL/Stats/TS.pd"
601             sub PDL::pred_ar {
602             my ($x, $b, $t, $opt) = @_;
603             my %opt = ( CONST => 1 );
604             if ($opt) { $opt{uc $_} = $opt->{$_} for keys %$opt; }
605             $b = PDL->topdl($b); # allows passing simple number
606             my $ext;
607             if ($opt{CONST}) {
608             my $t_ = $t - ( $x->dim(0) - $b->dim(0) + 1 );
609             PDL::_pred_ar_int($x->slice([-$b->dim(0)+1,-1]), $b->slice('0:-2'), $ext = PDL->null, $t_);
610             $ext->slice([$b->dim(0)-1,-1]) += $b->slice(-1);
611             return $x->append( $ext->slice([$b->dim(0)-1,-1]) );
612             } else {
613             my $t_ = $t - ( $x->dim(0) - $b->dim(0) );
614             PDL::_pred_ar_int($x->slice([-$b->dim(0),-1]), $b, $ext = PDL->null, $t_);
615             return $x->append($ext->slice([$b->dim(0),-1]));
616             }
617             }
618             #line 619 "lib/PDL/Stats/TS.pm"
619              
620             *pred_ar = \&PDL::pred_ar;
621              
622              
623              
624              
625              
626             #line 472 "lib/PDL/Stats/TS.pd"
627              
628             #line 473 "lib/PDL/Stats/TS.pd"
629              
630             =head2 season_m
631              
632             Given length of season, returns seasonal mean and variance for each period
633             (returns seasonal mean only in scalar context).
634              
635             =for options
636              
637             Default options (case insensitive):
638              
639             START_POSITION => 0, # series starts at this position in season
640             MISSING => -999, # internal mark for missing points in season
641             PLOT => 0, # boolean
642             # see PDL::Graphics::Simple for next options
643             WIN => undef, # pass pgswin object for more plotting control
644             COLOR => 1,
645              
646             =for usage
647              
648             my ($m, $ms) = $data->season_m( 24, { START_POSITION=>2 } );
649              
650             =cut
651              
652             *season_m = \&PDL::season_m;
653             sub PDL::season_m {
654             my ($self, $d, $opt) = @_;
655             my %opt = (
656             START_POSITION => 0, # series starts at this position in season
657             MISSING => -999, # internal mark for missing points in season
658             PLOT => 0,
659             WIN => undef, # pass pgswin object for more plotting control
660             COLOR => 1,
661             );
662             if ($opt) { $opt{uc $_} = $opt->{$_} for keys %$opt; }
663              
664             my $n_season = ($self->dim(0) + $opt{START_POSITION}) / $d;
665             $n_season = pdl($n_season)->ceil->sum->sclr;
666              
667             my @dims = $self->dims;
668             $dims[0] = $n_season * $d;
669             my $data = zeroes( @dims ) + $opt{MISSING};
670              
671             $data->slice([$opt{START_POSITION},$opt{START_POSITION} + $self->dim(0)-1]) .= $self;
672             $data->badflag(1);
673             $data->inplace->setvaltobad( $opt{MISSING} );
674              
675             my $s = sequence $d;
676             $s = $s->dummy(1, $n_season)->flat;
677             $s = $s->iv_cluster();
678              
679             my ($m, $ms) = $data->centroid( $s );
680              
681             if ($opt{PLOT}) {
682             require PDL::Graphics::Simple;
683             my $w = $opt{WIN} || PDL::Graphics::Simple::pgswin();
684             my $seq = sequence($d);
685             my $errb_length = sqrt( $ms / $s->sumover )->squeeze;
686             my $col = $opt{COLOR};
687             my @plots = map +(with=>'lines', ke=>"Data $col", style=>$col++, $seq, $_), $m->dog;
688             push @plots, with=>'errorbars', ke=>'Error', style=>$opt{COLOR}, $seq, $m->squeeze, $errb_length
689             if $m->squeeze->ndims < 2 && ($errb_length > 0)->any;
690             $w->plot(@plots, { xlabel=>'period', ylabel=>'mean' });
691             }
692              
693             return wantarray? ($m, $ms) : $m;
694             }
695              
696             =head2 plot_dseason
697              
698             =for ref
699              
700             Plots deseasonalized data and original data points. Opens and closes
701             default window for plotting unless a C object is passed in
702             options. Returns deseasonalized data.
703              
704             =for options
705              
706             Default options (case insensitive):
707              
708             WIN => undef,
709             COLOR => 1, # data point color
710              
711             =cut
712              
713             *plot_dseason = \&PDL::plot_dseason;
714             sub PDL::plot_dseason {
715             require PDL::Graphics::Simple;
716             my ($self, $d, $opt) = @_;
717             !defined($d) and croak "please set season period length";
718             $self = $self->squeeze;
719             my %opt = (
720             WIN => undef,
721             COLOR => 1, # data point color
722             );
723             if ($opt) { $opt{uc $_} = $opt->{$_} for keys %$opt; }
724             my $dsea = $self->dseason($d);
725             my $w = $opt{WIN} || PDL::Graphics::Simple::pgswin();
726             my $seq = sequence($self->dim(0));
727             my $col = $opt{COLOR};
728             my @plots = map +(with=>'lines', ke=>"Data $col", style=>$col++, $seq, $_), $dsea->dog;
729             $col = $opt{COLOR};
730             push @plots, map +(with=>'points', ke=>"De-seasonalised $col", style=>$col++, $seq, $_), $self->dog;
731             $w->plot(@plots, { xlabel=>'T', ylabel=>'DV' });
732             return $dsea;
733             }
734              
735             =head1 METHODS
736              
737             =head2 plot_acf
738              
739             =for ref
740              
741             Plots and returns autocorrelations for a time series.
742              
743             =for options
744              
745             Default options (case insensitive):
746              
747             SIG => 0.05, # can specify .10, .05, .01, or .001
748             WIN => undef,
749              
750             =for usage
751              
752             Usage:
753              
754             pdl> $a = sequence 10
755              
756             pdl> p $r = $a->plot_acf(5)
757             [1 0.7 0.41212121 0.14848485 -0.078787879 -0.25757576]
758              
759             =cut
760              
761             *plot_acf = \&PDL::plot_acf;
762             sub PDL::plot_acf {
763             require PDL::Graphics::Simple;
764             my $opt = ref($_[-1]) eq 'HASH' ? pop @_ : undef;
765             my ($self, $h) = @_;
766             my $r = $self->acf($h);
767             my %opt = (
768             SIG => 0.05,
769             WIN => undef,
770             );
771             if ($opt) { $opt{uc $_} = $opt->{$_} for keys %$opt; }
772             my $y_sig = ($opt{SIG} == 0.10)? 1.64485362695147
773             : ($opt{SIG} == 0.05)? 1.95996398454005
774             : ($opt{SIG} == 0.01)? 2.5758293035489
775             : ($opt{SIG} == 0.001)? 3.29052673149193
776             : 0
777             ;
778             unless ($y_sig) {
779             carp "SIG outside of recognized value. default to 0.05";
780             $y_sig = 1.95996398454005;
781             }
782             my $w = $opt{WIN} || PDL::Graphics::Simple::pgswin();
783             my $seq = pdl(-1,$h+1);
784             my $y_seq = ones(2) * $y_sig / sqrt($self->dim(0)) * -1;
785             $w->plot(
786             with=>'lines', $seq, zeroes(2), # x axis
787             with=>'lines', style=>2, $seq, $y_seq,
788             with=>'lines', style=>2, $seq, -$y_seq,
789             (map +(with=>'lines', ones(2)*$_, pdl(0, $r->slice("($_)"))), 0..$h), { xlabel=>'lag', ylabel=>'acf', }
790             );
791             $r;
792             }
793              
794             =head1 REFERENCES
795              
796             Brockwell, P.J., & Davis, R.A. (2002). Introduction to Time Series and Forecasting (2nd ed.). New York, NY: Springer.
797              
798             Schütz, W., & Kolassa, S. (2006). Foresight: advantages of the MAD/Mean ratio over the MAPE. Retrieved Jan 28, 2010, from http://www.saf-ag.com/226+M5965d28cd19.html
799              
800             =head1 AUTHOR
801              
802             Copyright (C) 2009 Maggie J. Xiong
803              
804             All rights reserved. There is no warranty. You are allowed to redistribute this software / documentation as described in the file COPYING in the PDL distribution.
805              
806             =cut
807             #line 808 "lib/PDL/Stats/TS.pm"
808              
809             # Exit with OK status
810              
811             1;