11
votes

Utiliser Perl pour trouver la médiane, le mode, l'écart type?

J'ai un tableau de chiffres. Quel est le moyen le plus simple de calculer la médiane, le mode et STD Dev pour le jeu de données?


0 commentaires

3 Réponses :


29
votes

2 commentaires

Pourquoi n'y a-t-il pas Statistiques :: basique :: max ou statistiques :: basique :: min dans ce module?


Parce qu'ils sont dans la liste :: util, qui est dans le noyau.



14
votes

En fonction de la profondeur, vous devez aller, la réponse d'Erickb peut fonctionner. Toutefois, pour la fonctionnalité numérique dans Perl, il y a pdl . Vous créeriez un piddle (l'objet contenant vos données) à l'aide du PDL fonction. À partir de là, vous pouvez utiliser les opérations sur Cette page pour faire les statistiques que vous avoir besoin.

Edit: En regardant autour de moi, j'ai trouvé deux appels de fonction qui font exactement ce dont vous avez besoin. STATSOVER donne des statistiques sur une dimension d'un pidon, tandis que statistiques fait la même chose sur tout le pid. xxx


3 commentaires

En fait, je n'avais pas entendu parler de PDL auparavant, je suppose que depuis la majeure partie de ce que j'ai fait a été le développement des outils Sysadmin et ce que rien. C'est vraiment vraiment cool, merci pour la pointe.


@Badfilemagic, j'ai été vraiment déçu après avoir vu une conversation sur une pensée engendrée / Scipy pensant que cela signifiait enfin que je devais quitter Perl pour Python. Puis j'ai trouvé pdl. Tout bon.


Jamais entendu ça avant. Semble incroyable!



16
votes
#!/usr/bin/perl
#
# stdev - figure N, min, max, median, mode, mean, & std deviation
#
# pull out all the real numbers in the input
# stream and run standard calculations on them.
# they may be intermixed with other test, need
# not be on the same or different lines, and 
# can be in scientific notion (avagadro=6.02e23).
# they also admit a leading + or -.
#
# Tom Christiansen
# tchrist@perl.com

use strict;
use warnings;

use List::Util qw< min max >;

sub by_number {
    if ($a < $b){ -1 } elsif ($a > $b) { 1 } else { 0 }
}


#
my $number_rx = qr{

  # leading sign, positive or negative
    (?: [+-] ? )

  # mantissa
    (?= [0123456789.] )
    (?: 
        # "N" or "N." or "N.N"
        (?:
            (?: [0123456789] +     )
            (?:
                (?: [.] )
                (?: [0123456789] * )
            ) ?
      |
        # ".N", no leading digits
            (?:
                (?: [.] )
                (?: [0123456789] + )
            ) 
        )
    )

  # abscissa
    (?:
        (?: [Ee] )
        (?:
            (?: [+-] ? )
            (?: [0123456789] + )
        )
        |
    )
}x;

my $n = 0;
my $sum = 0;
my @values = ();

my %seen = ();

while (<>) {
    while (/($number_rx)/g) {
        $n++;
        my $num = 0 + $1;  # 0+ is so numbers in alternate form count as same
        $sum += $num;
        push @values, $num;
        $seen{$num}++;
    } 
} 

die "no values" if $n == 0;

my $mean = $sum / $n;

my $sqsum = 0;
for (@values) {
    $sqsum += ( $_ ** 2 );
} 
$sqsum /= $n;
$sqsum -= ( $mean ** 2 );
my $stdev = sqrt($sqsum);

my $max_seen_count = max values %seen;
my @modes = grep { $seen{$_} == $max_seen_count } keys %seen;

my $mode = @modes == 1 
            ? $modes[0] 
            : "(" . join(", ", @modes) . ")";
$mode .= ' @ ' . $max_seen_count;

my $median;
my $mid = int @values/2;
my @sorted_values = sort by_number @values;
if (@values % 2) {
    $median = $sorted_values[ $mid ];
} else {
    $median = ($sorted_values[$mid-1] + $sorted_values[$mid])/2;
} 

my $min = min @values;
my $max = max @values;

printf "n is %d, min is %g, max is %g\n", $n, $min, $max;
printf "mode is %s, median is %g, mean is %g, stdev is %g\n", 
    $mode, $median, $mean, $stdev;

3 commentaires

Est-ce meilleur que sub by_number {return $ a <=> $ b} , pour une définition de "mieux"?


Qu'est-ce qui ne va pas avec mon @sorted_values ​​= Trier {$ A <=> $ b} @values; ?


@ hepcat72 c'est une bonne question, vraiment. Je ne me souviens plus pourquoi je l'ai fait.