Count occurences of a numeric string falling in a range

Dear all,

I have numerous dat files (1.dat, 2.dat...) containing 500 numeric values each. I would like to count them, based on their range and obtain a histogram or a counter.

INPUT:

1.dat
1.3
2.16
0.34
......

2.dat
1.54
0.94
3.13
.....

3.dat
2.34
4.12
2.7
.....

OUTPUT:
example-
1.dat: low (2>) - 200 ; medium (3> and 2<) - 50 ; high (3<) -250

(the output can be in any comprehensive format)

I used the following script, in vain!

Code:

#!/bin/csh
set k = 1
while ($k = 250)

set i=0
set low = 0
set medium = 0
set high = 0
foreach line ("`cat $k.dat`")
set j = `printf $line`
if ($j < 2) then
@low = $low +1
else if ($j > 2 and <3) then
@medium = $medium +1
else if ($j > 3) then
@high = $high +1
else
endif
end

echo "$k - $low $medium $high"
@k = $k +1
end

I get an error sayin "if: Badly formed number.
Could you please help?

Thanks,
Po

Place this script in the directory containing .dat files, then run it there.

#!/usr/bin/perl
chomp(@files=`ls *.dat`);
for $i (@files){
  open I, "$i";
  $l=$m=$h=0;
  while ($n=<I>){
    chomp $n;
    $l++ if $n<=2;
    $m++ if $n>2 && $n<=3;
    $h++ if $n>3;
  } 
  print "$i: low (2>) - $l ; medium (3> and 2<) - $m ; high (3<) - $h\n";
}
1 Like

Thanks Bartus11
:b:

Hi,

Other solution using 'perl' too:

$ cat script.pl
use warnings;
use strict;

die "Usage: perl $0 low-range medium-range high-range files\n" unless 
    @ARGV >= 4 and
    grep { /^-?\d+$/ } @ARGV[0..2] and    # Integer ranges.
    defined $ARGV[3];                    # At least one file.

my %range = (
    low_limit => shift,
    medium_limit => shift,
    high_limit => shift
);


while ( <> ) {
    ## Only count lines without number.
    if ( /^\s*\d+(?:\.\d*)\s*$/ ) {
        if ( $_ < $range{ low_limit } ) {
            $range{ low_num }++;    
        } elsif ( $_ >= $range{ low_limit } && $_ < $range{ medium_limit } ) {
            $range { medium_num }++;
        } elsif ( $_ >= $range{ high_limit } ) {
            $range{ high_num }++;
        }
    }

    ## Print result in end of each file.
    if ( eof ) {
        printf 
            "%s: low (%d<) - %d ; medium (>%d and %d<) - %d ; high (>%d) - %d\n", 
            $ARGV,
            $range{ low_limit },
            $range{ low_num } || 0,
            $range{ low_limit },
            $range{ medium_limit },
            $range{ medium_num } || 0,
            $range{ high_limit },
            $range{ high_num } || 0,
            delete @range{ qw(low_num medium_num high_num) }; 
    }
}
$ perl script.pl
Usage: perl script.pl low-range medium-range high-range files
$ perl script.pl 2 3 3 *.dat  # Output with my test files.
1.dat: low (2<) - 4 ; medium (>2 and 3<) - 1 ; high (>3) - 1
2.dat: low (2<) - 2 ; medium (>2 and 3<) - 1 ; high (>3) - 3

Regards,
Birei