File Coverage

blib/lib/Statistics/Frequency.pm
Criterion Covered Total %
statement 108 122 88.5
branch 39 54 72.2
condition 3 6 50.0
subroutine 18 18 100.0
pod 14 14 100.0
total 182 214 85.0


line stmt bran cond sub pod time code
1             package Statistics::Frequency;
2              
3 9     9   6860 use strict;
  9         17  
  9         1566  
4              
5 9     9   52 use vars qw($VERSION);
  9         14  
  9         16987  
6              
7             $VERSION = '0.03';
8              
9             sub elements {
10 20     20 1 89 my $self = shift;
11 20 50       69 exists $self->{data} ? keys %{$self->{data}} : wantarray ? () : undef;
  19 100       112  
12             }
13              
14             sub frequency {
15 117     117 1 206 my ($self, $e) = @_;
16 117 100       587 exists $self->{data} ? $self->{data}->{$e} : 0;
17             }
18              
19             sub add_data {
20 25     25 1 39 my $self = shift;
21 25         33 my $mod;
22 25         51 for my $data (@_) {
23 174         300 my $ref = ref $data;
24 174 50       469 if ($ref eq ref $self) {
25 0         0 for my $e ($data->elements) {
26 0         0 $self->{data}->{$e} += $data->frequency($e);
27 0         0 $mod++;
28             }
29 174 100       387 } if ($ref eq 'HASH') {
    100          
30 5         10 for my $e (keys %{$data}) {
  5         23  
31 24         47 $self->{data}->{$e} += $data->{$e};
32 24         45 $mod++;
33             }
34             } elsif ($ref eq 'ARRAY') {
35 4         33 $self->add_data(@$data);
36             } else {
37 165         397 $self->{data}->{$data}++;
38 165         240 $mod++;
39             }
40             }
41 25 100       75 if ($mod) {
42 18         26 delete @{$self}{qw(sum min max)};
  18         44  
43 18 50       70 $self->{update}->($self) if exists $self->{update};
44             }
45 25         65 return $self;
46             }
47              
48             sub _set_update_callback {
49 1     1   24 my ($self, $callback) = @_;
50 1         5 $self->{update} = $callback;
51             }
52              
53             sub remove_data {
54 3     3 1 5 my $self = shift;
55 3         4 my $mod;
56 3         7 for my $data (@_) {
57 3         4 my $ref = ref $data;
58 3 50 33     10 if ($ref && $data->isa(ref $self)) {
59 0         0 for my $e ($data->elements) {
60 0         0 $self->{data}->{$e} -= $data->frequency($e);
61 0         0 $mod++;
62             }
63 3 50       12 } if ($ref eq 'HASH') {
    50          
64 0         0 for my $e (keys %{$data}) {
  0         0  
65 0         0 $self->{data}->{$e} -= $data->{$e};
66 0         0 $mod++;
67             }
68             } elsif ($ref eq 'ARRAY') {
69 0         0 for my $e (@{$data}) {
  0         0  
70 0         0 $self->{data}->{$e}--;
71 0         0 $mod++;
72             }
73             } else {
74 3         8 $self->{data}->{$data}--;
75 3         5 $mod++;
76             }
77 3         16 for my $e ($self->elements) {
78 12 100       42 delete $self->{data}->{$e} if $self->{data}->{$e} <= 0;
79             }
80             }
81 3 50       9 if ($mod) {
82 3         4 delete @{$self}{qw(sum min max)};
  3         6  
83 3 50       9 $self->{update}->($self) if exists $self->{update};
84             }
85 3         13 return $self;
86             }
87              
88             sub remove_elements {
89 3     3 1 5 my $self = shift;
90 3         10 my $mod;
91 3         6 for my $e (@_) {
92 3         8 delete $self->{data}->{$e};
93 3         7 $mod++;
94             }
95 3 50       67 if ($mod) {
96 3 50       4 delete $self->{data} unless keys %{$self->{data}};
  3         12  
97 3         5 delete @{$self}{qw(sum min max)};
  3         7  
98 3 50       10 $self->{update}->($self) if exists $self->{update};
99             }
100 3         12 return $self;
101             }
102              
103             sub clear_data {
104 2     2 1 25 my $self = shift;
105 2         9 delete $self->{data};
106 2         4 delete @{$self}{qw(sum min max)};
  2         7  
107 2 100       13 $self->{update}->($self) if exists $self->{update};
108 2         9 return $self;
109             }
110              
111             sub copy_data {
112 1     1 1 10 my $self = shift;
113 1         4 my $copy = (ref $self)->new;
114 1         4 $copy->add_data($self->{data});
115 1         3 return $copy;
116             }
117              
118             sub frequencies {
119 24     24 1 33 my $self = shift;
120 24 50       70 exists $self->{data} ? %{$self->{data}} : ();
  24         1245  
121             }
122              
123             sub _frequencies_stats {
124 15     15   22 my $self = shift;
125 15 50       53 unless (exists $self->{sum}) {
126 15         21 my $sum;
127             my $min;
128 14         38 my $max = $min =
129             exists $self->{data} ?
130 15 100       58 $self->{data}->{each %{$self->{data}}} : undef;
131 15         26 for my $f (values %{$self->{data}}) {
  15         65  
132 59         62 $sum += $f;
133 59 100       165 if ($f < $min) { $min = $f } elsif ($f > $max) { $max = $f }
  12 100       18  
  12         38  
134             }
135 15         40 $self->{sum} = $sum;
136 15         31 $self->{min} = $min;
137 15         41 $self->{max} = $max;
138             }
139             }
140              
141             sub frequencies_sum {
142 75     75 1 1205 my $self = shift;
143 75 100       210 $self->_frequencies_stats unless exists $self->{sum};
144 75         150 return $self->{sum};
145             }
146              
147             sub frequencies_min {
148 12     12 1 26 my $self = shift;
149 12 50       38 $self->_frequencies_stats unless exists $self->{min};
150 12         47 return $self->{min};
151             }
152              
153             sub frequencies_max {
154 12     12 1 21 my $self = shift;
155 12 50       35 $self->_frequencies_stats unless exists $self->{max};
156 12         76 return $self->{max};
157             }
158              
159             sub proportional_frequencies {
160 12     12 1 25 my $self = shift;
161 12         31 my %prop = $self->frequencies;
162 12         38 my $sum = $self->frequencies_sum;
163 12         40 for my $e (keys %prop) { $prop{$e} /= $sum }
  39         77  
164 12         185 return %prop;
165             }
166              
167             sub proportional_frequency {
168 48     48 1 464 my ($self, $e) = @_;
169 48         94 my $freq = $self->frequency($e);
170 48         110 my $sum = $self->frequencies_sum;
171 48 100 66     295 defined $freq && $sum ? $freq / $sum : undef;
172             }
173              
174             sub new {
175 17     17 1 450 my $class = shift;
176 17         54 my $self = bless { }, $class;
177 17         89 $self->add_data(@_);
178 17         62 return $self;
179             }
180              
181             1;
182             __END__