Reputation: 10546
The Statistics::Descriptive
module provides the Full
class that allows you to compute a trimmed mean. Is there a way to get a trimmed standard deviation out of it? It's already sorting the data to get the trimmed mean, so the hard part is done.
Upvotes: 3
Views: 828
Reputation: 899
If your data is all positive, or all negative numbers, then you can just keep 2 $stat objects, one for plain values and one for the squared values, and combine the trimmed_mean results to generate trimmed stddev:
my $stat_x = Statistics::Descriptive::Full->new();
my $stat_xx = Statistics::Descriptive::Full->new();
sub add_x {
$stat_x->add_data( @_ );
$stat_xx->add_data( map {$_*$_} @_ );
}
sub trimmed_stddev {
my $lower = shift;
my $upper = @_ ? shift : $lower;
my $trm_x = $stat_x->trimmed_mean( $lower, $upper );
my $trm_xx = $stat_xx->trimmed_mean( $lower, $upper );
my $nn = int( $stat_x->count() * ( 1.0 - $lower - $upper ) );
return ($nn <= 1 ? 0.0 : sqrt(($trm_xx - $trm_x * $trm_x ) * $nn / ($nn -1)) );
}
# add some data
add_x( 1, 5, 12, 29, 10, 11, 2 );
print trimmed_stddev(0.0);
print trimmed_stddev(0.05);
print trimmed_stddev(0.2);
# output
# 9.45163125250522
# 9.58570364061576
# 4.44222166638871
Upvotes: 3