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