@@ -20,7 +20,10 @@ my $builder = Test::Run::Builder->new(
},
requires => {
'Carp' => 0,
+ 'List::MoreUtils' => 0,
+ 'List::Util' => 0,
'POSIX' => 0,
+ 'perl' => '5.006',
'strict' => 0,
'vars' => 0,
'warnings' => 0,
@@ -1,5 +1,22 @@
Revision history for Perl extension Statistics::Descriptive.
+3.0608 2015-01-14
+ - Apply patch to speed up skewness calculations.
+ - https://rt.cpan.org/Public/Bug/Display.html?id=101422
+ - Thanks to Shawn (SLAFFAN).
+
+3.0607 2014-02-01
+ - Fix the List::MoreUtils prereqs.
+ - http://www.cpantesters.org/cpan/report/365b752c-8adf-11e3-bd14-e3bee4621ba3
+ - Thanks to Chris Williams (BINGOS) for the CPAN Testers Report.
+
+3.0606 2014-01-31
+ - Implement the median_absolute_deviation method.
+ - https://bitbucket.org/shlomif/perl-statistics-descriptive/pull-request/5/median-absolute-deviation-method/diff
+ - Thanks to Kang-min Liu.
+ - Minimal version of perl set to 5.6.0 (CPANTS).
+ - Add standalone LICENSE file (CPANTS).
+
3.0605 2013-05-21
- Add t/style-trailing-space.t .
- Add t/cpan-changes.t .
@@ -0,0 +1,396 @@
+Terms of Perl itself
+
+a) the GNU General Public License as published by the Free
+ Software Foundation; either version 1, or (at your option) any
+ later version, or
+b) the "Artistic License"
+
+----------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+----------------------------------------------------------------------------
+
+The Artistic License
+
+Preamble
+
+The intent of this document is to state the conditions under which a Package
+may be copied, such that the Copyright Holder maintains some semblance of
+artistic control over the development of the package, while giving the users of the
+package the right to use and distribute the Package in a more-or-less customary
+fashion, plus the right to make reasonable modifications.
+
+Definitions:
+
+- "Package" refers to the collection of files distributed by the Copyright
+ Holder, and derivatives of that collection of files created through textual
+ modification.
+- "Standard Version" refers to such a Package if it has not been modified,
+ or has been modified in accordance with the wishes of the Copyright
+ Holder.
+- "Copyright Holder" is whoever is named in the copyright or copyrights for
+ the package.
+- "You" is you, if you're thinking about copying or distributing this Package.
+- "Reasonable copying fee" is whatever you can justify on the basis of
+ media cost, duplication charges, time of people involved, and so on. (You
+ will not be required to justify it to the Copyright Holder, but only to the
+ computing community at large as a market that must bear the fee.)
+- "Freely Available" means that no fee is charged for the item itself, though
+ there may be fees involved in handling the item. It also means that
+ recipients of the item may redistribute it under the same conditions they
+ received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you duplicate
+all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications derived from
+the Public Domain or from the Copyright Holder. A Package modified in such a
+way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and when
+you changed that file, and provided that you do at least ONE of the following:
+
+ a) place your modifications in the Public Domain or otherwise
+ make them Freely Available, such as by posting said modifications
+ to Usenet or an equivalent medium, or placing the modifications on
+ a major archive site such as ftp.uu.net, or by allowing the
+ Copyright Holder to include your modifications in the Standard
+ Version of the Package.
+
+ b) use the modified Package only within your corporation or
+ organization.
+
+ c) rename any non-standard executables so the names do not
+ conflict with standard executables, which must also be provided,
+ and provide a separate manual page for each non-standard
+ executable that clearly documents how it differs from the Standard
+ Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or executable
+form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library
+ files, together with instructions (in the manual page or equivalent)
+ on where to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) accompany any non-standard executables with their
+ corresponding Standard Version executables, giving the
+ non-standard executables non-standard names, and clearly
+ documenting the differences in manual pages (or equivalent),
+ together with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this Package.
+You may charge any fee you choose for support of this Package. You may not
+charge a fee for this Package itself. However, you may distribute this Package in
+aggregate with other (possibly commercial) programs as part of a larger
+(possibly commercial) software distribution provided that you do not advertise
+this Package as a product of your own.
+
+6. The scripts and library files supplied as input to or produced as output from
+the programs of this Package do not automatically fall under the copyright of this
+Package, but belong to whomever generated them, and may be sold
+commercially, and may be aggregated with this Package.
+
+7. C or perl subroutines supplied by you and linked into this Package shall not
+be considered part of this Package.
+
+8. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The End
+
@@ -1,6 +1,8 @@
Build.PL
Changes
+LICENSE
MANIFEST
+META.json
META.yml
Makefile.PL
README
@@ -12,14 +14,15 @@ lib/Statistics/Descriptive/Smoother.pm
lib/Statistics/Descriptive/Smoother/Exponential.pm
lib/Statistics/Descriptive/Smoother/Weightedexponential.pm
rejects/descr.t
-scripts/tag-release.pl
scripts/bump-version-number.pl
-t/lib/Utils.pm
+scripts/tag-release.pl
t/00-load.t
t/cpan-changes.t
t/descr.t
t/descr_smooth_methods.t
t/freq_distribution-1-rt-34999.t
+t/lib/Utils.pm
+t/median_absolute_deviation.t
t/mode.t
t/outliers.t
t/pod-coverage.t
@@ -29,4 +32,3 @@ t/smoother.t
t/smoother_exponential.t
t/smoother_weightedexponential.t
t/style-trailing-space.t
-META.json
@@ -4,7 +4,7 @@
"Shlomi Fish <shlomif@iglu.org.il>"
],
"dynamic_config" : 1,
- "generated_by" : "Module::Build version 0.3901, CPAN::Meta::Converter version 2.120921",
+ "generated_by" : "Module::Build version 0.421",
"keywords" : [
"average",
"distribution",
@@ -39,7 +39,10 @@
"runtime" : {
"requires" : {
"Carp" : "0",
+ "List::MoreUtils" : "0",
+ "List::Util" : "0",
"POSIX" : "0",
+ "perl" : "5.006",
"strict" : "0",
"vars" : "0",
"warnings" : "0"
@@ -49,27 +52,27 @@
"provides" : {
"Statistics::Descriptive" : {
"file" : "lib/Statistics/Descriptive.pm",
- "version" : "3.0605"
+ "version" : "3.0608"
},
"Statistics::Descriptive::Full" : {
"file" : "lib/Statistics/Descriptive.pm",
- "version" : "3.0605"
+ "version" : "3.0608"
},
"Statistics::Descriptive::Smoother" : {
"file" : "lib/Statistics/Descriptive/Smoother.pm",
- "version" : "3.0605"
+ "version" : "3.0608"
},
"Statistics::Descriptive::Smoother::Exponential" : {
"file" : "lib/Statistics/Descriptive/Smoother/Exponential.pm",
- "version" : "3.0605"
+ "version" : "3.0608"
},
"Statistics::Descriptive::Smoother::Weightedexponential" : {
"file" : "lib/Statistics/Descriptive/Smoother/Weightedexponential.pm",
- "version" : "3.0605"
+ "version" : "3.0608"
},
"Statistics::Descriptive::Sparse" : {
"file" : "lib/Statistics/Descriptive.pm",
- "version" : "3.0605"
+ "version" : "3.0608"
}
},
"release_status" : "stable",
@@ -82,5 +85,5 @@
"url" : "https://bitbucket.org/shlomif/perl-statistics-descriptive"
}
},
- "version" : "3.0605"
+ "version" : "3.0608"
}
@@ -3,13 +3,13 @@ abstract: 'Module of basic descriptive statistical functions.'
author:
- 'Shlomi Fish <shlomif@iglu.org.il>'
build_requires:
- Benchmark: 0
- Test::More: 0
- lib: 0
+ Benchmark: '0'
+ Test::More: '0'
+ lib: '0'
configure_requires:
- Module::Build: 0.36
+ Module::Build: '0.36'
dynamic_config: 1
-generated_by: 'Module::Build version 0.3901, CPAN::Meta::Converter version 2.120921'
+generated_by: 'Module::Build version 0.421, CPAN::Meta::Converter version 2.142060'
keywords:
- average
- distribution
@@ -22,35 +22,38 @@ keywords:
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
- version: 1.4
+ version: '1.4'
name: Statistics-Descriptive
provides:
Statistics::Descriptive:
file: lib/Statistics/Descriptive.pm
- version: 3.0605
+ version: '3.0608'
Statistics::Descriptive::Full:
file: lib/Statistics/Descriptive.pm
- version: 3.0605
+ version: '3.0608'
Statistics::Descriptive::Smoother:
file: lib/Statistics/Descriptive/Smoother.pm
- version: 3.0605
+ version: '3.0608'
Statistics::Descriptive::Smoother::Exponential:
file: lib/Statistics/Descriptive/Smoother/Exponential.pm
- version: 3.0605
+ version: '3.0608'
Statistics::Descriptive::Smoother::Weightedexponential:
file: lib/Statistics/Descriptive/Smoother/Weightedexponential.pm
- version: 3.0605
+ version: '3.0608'
Statistics::Descriptive::Sparse:
file: lib/Statistics/Descriptive.pm
- version: 3.0605
+ version: '3.0608'
requires:
- Carp: 0
- POSIX: 0
- strict: 0
- vars: 0
- warnings: 0
+ Carp: '0'
+ List::MoreUtils: '0'
+ List::Util: '0'
+ POSIX: '0'
+ perl: '5.006'
+ strict: '0'
+ vars: '0'
+ warnings: '0'
resources:
homepage: http://web-cpan.berlios.de/modules/Statistics-Descriptive/
license: http://dev.perl.org/licenses/
repository: https://bitbucket.org/shlomif/perl-statistics-descriptive
-version: 3.0605
+version: '3.0608'
@@ -1,4 +1,5 @@
-# Note: this file was auto-generated by Module::Build::Compat version 0.39_01
+# Note: this file was auto-generated by Module::Build::Compat version 0.4210
+require 5.006;
use ExtUtils::MakeMaker;
WriteMakefile
(
@@ -7,6 +8,8 @@ WriteMakefile
'PREREQ_PM' => {
'Benchmark' => 0,
'Carp' => 0,
+ 'List::MoreUtils' => 0,
+ 'List::Util' => 0,
'POSIX' => 0,
'Test::More' => 0,
'lib' => 0,
@@ -4,7 +4,7 @@ use warnings;
use base 'Statistics::Descriptive::Smoother';
-our $VERSION = '3.0605';
+our $VERSION = '3.0608';
sub _new {
my ($class, $args) = @_;
@@ -5,7 +5,7 @@ use warnings;
use Carp;
use base 'Statistics::Descriptive::Smoother';
-our $VERSION = '3.0605';
+our $VERSION = '3.0608';
sub _new {
my ($class, $args) = @_;
@@ -5,7 +5,7 @@ use warnings;
use Carp;
-our $VERSION = '3.0605';
+our $VERSION = '3.0608';
sub instantiate {
my ($class, $args) = @_;
@@ -5,12 +5,11 @@ use warnings;
##This module draws heavily from perltoot v0.4 from Tom Christiansen.
-require 5.00404; ##Yes, this is underhanded, but makes support for me easier
- ##Not only that, but it's the latest "safe" version of
- ##Perl5. 01-03 weren't bug free.
+use 5.006;
+
use vars (qw($VERSION $Tolerance $Min_samples_number));
-$VERSION = '3.0605';
+$VERSION = '3.0608';
$Tolerance = 0.0;
$Min_samples_number = 4;
@@ -19,7 +18,7 @@ package Statistics::Descriptive::Sparse;
use vars qw($VERSION);
-$VERSION = '3.0605';
+$VERSION = '3.0608';
use vars qw(%fields);
use Carp;
@@ -113,75 +112,76 @@ sub _is_permitted
}
sub add_data {
- my $self = shift; ##Myself
- my $oldmean;
- my ($min,$mindex,$max,$maxdex,$sum,$sumsq,$count);
- my $aref;
-
- if (ref $_[0] eq 'ARRAY') {
- $aref = $_[0];
- }
- else {
- $aref = \@_;
- }
+ my $self = shift; ##Myself
+ my $oldmean;
+ my ($min,$mindex,$max,$maxdex,$sum,$sumsq,$count);
+ my $aref;
- ##If we were given no data, we do nothing.
- return 1 if (!@{ $aref });
+ if (ref $_[0] eq 'ARRAY') {
+ $aref = $_[0];
+ }
+ else {
+ $aref = \@_;
+ }
- ##Take care of appending to an existing data set
+ ##If we were given no data, we do nothing.
+ return 1 if (!@{ $aref });
- if (!defined($min = $self->min()))
- {
- $min = $aref->[$mindex = 0];
- }
- else
- {
- $mindex = $self->mindex();
- }
+ ##Take care of appending to an existing data set
- if (!defined($max = $self->max()))
- {
- $max = $aref->[$maxdex = 0];
- }
- else
- {
- $maxdex = $self->maxdex();
- }
+ if (!defined($min = $self->min()))
+ {
+ $min = $aref->[$mindex = 0];
+ }
+ else
+ {
+ $mindex = $self->mindex();
+ }
- $sum = $self->sum();
- $sumsq = $self->sumsq();
- $count = $self->count();
-
- ##Calculate new mean, sumsq, min and max;
- foreach ( @{ $aref } ) {
- $sum += $_;
- $sumsq += $_**2;
- $count++;
- if ($_ >= $max) {
- $max = $_;
- $maxdex = $count-1;
+ if (!defined($max = $self->max()))
+ {
+ $max = $aref->[$maxdex = 0];
}
- if ($_ <= $min) {
- $min = $_;
- $mindex = $count-1;
+ else
+ {
+ $maxdex = $self->maxdex();
}
- }
- $self->min($min);
- $self->mindex($mindex);
- $self->max($max);
- $self->maxdex($maxdex);
- $self->sample_range($max - $min);
- $self->sum($sum);
- $self->sumsq($sumsq);
- $self->mean($sum / $count);
- $self->count($count);
- ##indicator the value is not cached. Variance isn't commonly enough
- ##used to recompute every single data add.
- $self->_variance(undef);
- return 1;
+ $sum = $self->sum();
+ $sumsq = $self->sumsq();
+ $count = $self->count();
+
+ ##Calculate new mean, sumsq, min and max;
+ foreach ( @{ $aref } ) {
+ $sum += $_;
+ $sumsq += $_**2;
+ $count++;
+ if ($_ >= $max) {
+ $max = $_;
+ $maxdex = $count-1;
+ }
+ if ($_ <= $min) {
+ $min = $_;
+ $mindex = $count-1;
+ }
+ }
+
+ $self->min($min);
+ $self->mindex($mindex);
+ $self->max($max);
+ $self->maxdex($maxdex);
+ $self->sample_range($max - $min);
+ $self->sum($sum);
+ $self->sumsq($sumsq);
+ $self->mean($sum / $count);
+ $self->count($count);
+ ##indicator the value is not cached. Variance isn't commonly enough
+ ##used to recompute every single data add.
+ $self->_variance(undef);
+ return 1;
}
+
sub standard_deviation {
my $self = shift; ##Myself
return undef if (!$self->count());
@@ -190,35 +190,34 @@ sub standard_deviation {
##Return variance; if needed, compute and cache it.
sub variance {
- my $self = shift; ##Myself
+ my $self = shift; ##Myself
- return undef if (!$self->count());
+ my $count = $self->count();
- my $div = @_ ? 0 : 1;
- my $count = $self->count();
- if ($count < 1 + $div) {
- return 0;
- }
+ return undef if !$count;
- if (!defined($self->_variance())) {
- my $variance = ($self->sumsq()- $count * $self->mean()**2);
+ return 0 if $count == 1;
- # Sometimes due to rounding errors we get a number below 0.
- # This makes sure this is handled as gracefully as possible.
- #
- # See:
- #
- # https://rt.cpan.org/Public/Bug/Display.html?id=46026
- if ($variance < 0)
- {
- $variance = 0;
- }
+ if (!defined($self->_variance())) {
+ my $variance = ($self->sumsq()- $count * $self->mean()**2);
- $variance /= $count - $div;
+ # Sometimes due to rounding errors we get a number below 0.
+ # This makes sure this is handled as gracefully as possible.
+ #
+ # See:
+ #
+ # https://rt.cpan.org/Public/Bug/Display.html?id=46026
- $self->_variance($variance);
- }
- return $self->_variance();
+ $variance = $variance < 0 ? 0 : $variance / ($count - 1);
+
+ $self->_variance($variance);
+
+ # Return now to avoid re-entering this sub
+ # (and therefore save time when many objects are used).
+ return $variance;
+ }
+
+ return $self->_variance();
}
##Clear a stat. More efficient than destroying an object and calling
@@ -228,7 +227,7 @@ sub clear {
my $key;
return if (!$self->count());
- while (my($field, $value) = each %fields) {
+ while (my($field, $value) = each %fields) { # could use a slice assignment here
$self->{$field} = $value;
}
}
@@ -239,7 +238,7 @@ package Statistics::Descriptive::Full;
use vars qw($VERSION);
-$VERSION = '3.0605';
+$VERSION = '3.0608';
use Carp;
use POSIX ();
@@ -249,6 +248,9 @@ use vars qw(@ISA $a $b %fields);
@ISA = qw(Statistics::Descriptive::Sparse);
+use List::MoreUtils ();
+use List::Util ();
+
##Create a list of fields not to remove when data is updated
%fields = (
_permitted => undef, ##Place holder for the inherited key hash
@@ -261,7 +263,7 @@ use vars qw(@ISA $a $b %fields);
__PACKAGE__->_make_private_accessors(
[qw(data samples frequency geometric_mean harmonic_mean
least_squares_fit median mode
- skewness kurtosis
+ skewness kurtosis median_absolute_deviation
)
]
);
@@ -305,15 +307,18 @@ sub _delete_all_cached_keys
{
my $self = shift;
+ my %keys = %{ $self };
+
+ # Remove reserved keys for this class from the deletion list
+ delete @keys{keys %{$self->_reserved}};
+ delete @keys{keys %{$self->_permitted}};
+ delete $keys{_trimmed_mean_cache};
+
KEYS_LOOP:
- foreach my $key (keys %{ $self }) { # Check each key in the object
- # If it's a reserved key for this class, keep it
- if ($self->_is_reserved($key) || $self->_is_permitted($key))
- {
- next KEYS_LOOP;
- }
- delete $self->{$key}; # Delete the out of date cached key
+ foreach my $key (keys %keys) { # Check each key in the object
+ delete $self->{$key}; # Delete any out of date cached key
}
+ $self->{_trimmed_mean_cache} = {}; # just reset this one
return;
}
@@ -334,25 +339,76 @@ sub clear {
}
sub add_data {
- my $self = shift;
- my $aref;
+ my $self = shift; ##Myself
- if (ref $_[0] eq 'ARRAY') {
- $aref = $_[0];
- }
- else {
- $aref = \@_;
- }
- $self->SUPER::add_data($aref); ##Perform base statistics on the data
- push @{ $self->_data() }, @{ $aref };
- ##Clear the presorted flag
- $self->presorted(0);
+ my $aref;
+
+ if (ref $_[0] eq 'ARRAY') {
+ $aref = $_[0];
+ }
+ else {
+ $aref = \@_;
+ }
- $self->_delete_all_cached_keys();
+ ##If we were given no data, we do nothing.
+ return 1 if (!@{ $aref });
- return 1;
+ my $oldmean;
+ my ($min, $max, $sum, $sumsq);
+ my $count = $self->count;
+
+ # $count is modified lower down, but we need this flag after that
+ my $has_existing_data = $count;
+
+ # Take care of appending to an existing data set
+ if ($has_existing_data) {
+ $min = $self->min();
+ $max = $self->max();
+ $sum = $self->sum();
+ $sumsq = $self->sumsq();
+ }
+ else {
+ $min = $aref->[0];
+ $max = $aref->[0];
+ $sum = 0;
+ $sumsq = 0;
+ }
+
+ # need to allow for already having data
+ $sum += List::Util::sum (@$aref);
+ $sumsq += List::Util::sum (map {$_ ** 2} @$aref);
+ $max = List::Util::max ($max, @$aref);
+ $min = List::Util::min ($min, @$aref);
+ $count += scalar @$aref;
+ my $mean = $sum / $count;
+
+ $self->min($min);
+ $self->max($max);
+ $self->sample_range($max - $min);
+ $self->sum($sum);
+ $self->sumsq($sumsq);
+ $self->mean($mean);
+ $self->count($count);
+
+ ##Variance isn't commonly enough
+ ##used to recompute every single data add, so just clear its cache.
+ $self->_variance(undef);
+
+ push @{ $self->_data() }, @{ $aref };
+
+ # no need to clear keys if we are a newly populated object,
+ # and profiling shows it takes a long time when creating
+ # and populating many stats objects
+ if ($has_existing_data) {
+ ##Clear the presorted flag
+ $self->presorted(0);
+ $self->_delete_all_cached_keys();
+ }
+
+ return 1;
}
+
sub add_data_with_samples {
my ($self,$aref_values) = @_;
@@ -446,6 +502,46 @@ sub get_smoothed_data {
$self->{_smoother}->get_smoothed_data();
}
+sub maxdex {
+ my $self = shift;
+
+ return undef if !$self->count;
+ my $maxdex;
+
+ if ($self->presorted) {
+ $maxdex = $self->count - 1;
+ }
+ else {
+ my $max = $self->max;
+ $maxdex = List::MoreUtils::first_index {$_ == $max} $self->get_data;
+ }
+
+ $self->{maxdex} = $maxdex;
+
+ return $maxdex;
+}
+
+sub mindex {
+ my $self = shift;
+
+ return undef if !$self->count;
+ #my $maxdex = $self->{maxdex};
+ #return $maxdex if defined $maxdex;
+ my $mindex;
+
+ if ($self->presorted) {
+ $mindex = 0;
+ }
+ else {
+ my $min = $self->min;
+ $mindex = List::MoreUtils::first_index {$_ == $min} $self->get_data;
+ }
+
+ $self->{mindex} = $mindex;
+
+ return $mindex;
+}
+
sub sort_data {
my $self = shift;
@@ -454,9 +550,9 @@ sub sort_data {
##Sort the data in descending order
$self->_data([ sort {$a <=> $b} @{$self->_data()} ]);
$self->presorted(1);
- ##Fix the maxima and minima indices
- $self->mindex(0);
- $self->maxdex($#{$self->_data()});
+ ##Fix the maxima and minima indices - no, this is unnecessary now we have methods
+ #$self->mindex(0);
+ #$self->maxdex($#{$self->_data()});
}
return 1;
@@ -727,12 +823,11 @@ sub skewness {
my $mean = $self->mean();
my $sum_pow3;
-
foreach my $rec ( $self->get_data ) {
- my $value = (($rec - $mean) / $sd);
- $sum_pow3 += $value ** 3;
+ $sum_pow3 += (($rec - $mean) / $sd) ** 3;
}
+
my $correction = $n / ( ($n-1) * ($n-2) );
$skew = $correction * $sum_pow3;
@@ -752,7 +847,7 @@ sub kurtosis {
my $kurt;
my $n = $self->count();
- my $sd = $self->standard_deviation();
+ my $sd = $self->standard_deviation();
if ( $sd && $n > 3) {
@@ -920,6 +1015,20 @@ sub least_squares_fit {
return @{ $self->_least_squares_fit() };
}
+sub median_absolute_deviation {
+ my ($self) = @_;
+
+ if (!defined($self->_median_absolute_deviation()))
+ {
+ my $stat = $self->new;
+ $stat->add_data(map { abs($_ - $self->median) } $self->get_data);
+ $self->_median_absolute_deviation($stat->median);
+ }
+
+ return $self->_median_absolute_deviation();
+}
+
+
1;
package Statistics::Descriptive;
@@ -3,7 +3,7 @@
use strict;
use warnings;
-use Test::More tests => 54;
+use Test::More tests => 61;
use lib 't/lib';
use Utils qw/is_between compare_hash_by_ranges/;
@@ -452,3 +452,71 @@ use Statistics::Descriptive;
);
}
+
+# Tests for mindex and maxdex on unsorted data,
+# including when new data are added which should not change the values
+{
+ my $stats_class = 'Statistics::Descriptive::Full';
+ my $stat1 = $stats_class->new();
+
+ my @data1 = (20, 1 .. 3, 100, 1..5);
+ my @data2 = (25, 30);
+
+ my $e_maxdex = 4;
+ my $e_mindex = 1;
+
+ $stat1->add_data(@data1); # initialise
+
+ # TEST*2
+ is ($stat1->mindex, $e_mindex, "initial mindex is correct");
+ is ($stat1->maxdex, $e_maxdex, "initial maxdex is correct");
+
+ # TEST*2
+ $stat1->add_data(@data2); # add new data
+ is ($stat1->mindex, $e_mindex, "mindex is correct after new data added");
+ is ($stat1->maxdex, $e_maxdex, "maxdex is correct after new data added");
+
+ # TEST*2
+ $stat1->median; # trigger a sort
+ $e_maxdex = scalar @data1 + scalar @data2 - 1;
+ is ($stat1->mindex, 0, "mindex is correct after sorting");
+ is ($stat1->maxdex, $e_maxdex, "maxdex is correct after sorting");
+
+}
+
+
+# what happens when we add new data?
+# Recycle the same data so mean, sd etc remain the same
+{
+ my $stats_class = 'Statistics::Descriptive::Full';
+ my $stat1 = $stats_class->new();
+ my $stat2 = $stats_class->new();
+
+ my @data1 = (1 .. 9, 100);
+ my @data2 = (100 .. 110);
+
+ # sample of methods
+ my @methods = qw /mean standard_deviation count skewness kurtosis median/;
+
+ $stat1->add_data(@data1); # initialise
+ foreach my $meth (@methods) { # run some methods
+ $stat1->$meth;
+ }
+ $stat1->add_data(@data2); # add new data
+ foreach my $meth (@methods) { # re-run some methods
+ $stat1->$meth;
+ }
+
+ $stat2->add_data(@data1, @data2); # initialise with all data
+ foreach my $meth (@methods) { # run some methods
+ $stat2->$meth;
+ }
+
+ # TEST
+ is_deeply (
+ $stat1,
+ $stat2,
+ 'stats consistent after adding new data',
+ );
+
+}
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use Statistics::Descriptive;
+
+{
+ my $stat = Statistics::Descriptive::Full->new();
+
+ $stat->add_data( 1, 1, 1, 2, 2, 2, 2, 4, 7 );
+
+ my $mad = $stat->median_absolute_deviation();
+
+ # TEST
+ ok (defined($mad),
+ "median_absolute_deviation is not undefined"
+ );
+
+ # TEST
+ is($mad, 1,
+ "median_absolute_deviation is correct"
+ );
+}