Reversing a conditional statement in perl to be everything except instead of only if

libertyforall2
libertyforall2 used Ask the Experts™
on
IN my original post http://www.experts-exchange.com/Programming/Languages/Scripting/Perl/Q_27283111.html I wanted to parse data into 6 categories. Each category had to meet specific conditions. Column 1 contained the categories, column 2 of the output file was the total number of times column 4 of the input file met the condition, column 3 of the output file was the total number of times both columns 3 & 4 of the same row met the condition. I am using the script below. Now I want the have the values for those categories where the condition is not met. So column 1 of the output file should contain the categories 1-6, column 2  should contains the total number of times in column 4 of the input file where the value does not meet the conditions for that category, & column three of the output file contains the total number of times where both columns 3 & 4 of the input file do not fall in the specified categories. The conditions are in the script and are a numerical range. I have attached a sample input file as well.

Original script

use strict;

my @observed;
my @same;
while( <> ) {
   chomp;
   my($forecasted, $observed) = (split)[-2,-1];
   my $observedCategory = valueToCategory($observed);
   my $forecastedCategory = valueToCategory($forecasted);
   $observed[ $observedCategory ]++;
   $same[ $observedCategory ]++ if $observedCategory == $forecastedCategory;
}

foreach my $category(1..6) {
   my $observed   = $observed[$category]  || 0;
   my $same       = $same[$category]      || 0;
   printf("$category %3d %3d %5.1f\n", $observed, $same, $observed ? ($same*100)/$observed : 0);
}


sub valueToCategory {
   my($value) = @_;

   my $category;
   if( $value <= .1 )    { $category = 1 }
   elsif( $value <= .2 ) { $category = 2 }
   elsif( $value <=  1 ) { $category = 3 }
   elsif( $value <=  3 ) { $category = 4 }
   elsif( $value <=  5 ) { $category = 5 }
   else                  { $category = 6 }

   return $category;
}

Open in new window

so2pamerged.txt
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
ozo
Most Valuable Expert 2014
Top Expert 2015

Commented:
#if I understand what you are asking for, it sounds like you want a change like this:
while( <> ) {
   chomp;
   my($forecasted, $observed) = (split)[-2,-1];
   my $observedCategory = valueToCategory($observed);
   my $forecastedCategory = valueToCategory($forecasted);
   $observed[ $observedCategory ]++;
   $same[ $observedCategory ]++ if $observedCategory == $forecastedCategory;
   $total++;
}

foreach my $category(1..6) {
   my $observed   = $observed[$category]  || 0;
   my $same       = $same[$category]      || 0;
   printf("$category %3d %3d %5.1f\n", $total-$observed, $total-$same, $observed ? ($same*100)/$observed : 0);
}

Author

Commented:
I'm getting the error messages below when I make the changes.


[rhuff@huina ~/forecastfiles]$ perl /share/huina/rhuff/forecastfiles/categoryso4rv.pl 25knmergedebias3post.txt > so4knbias3categoriesrv.txt
Global symbol "$total" requires explicit package name at /share/huina/rhuff/forecastfiles/categoryso4rv.pl line 12.
Global symbol "$total" requires explicit package name at /share/huina/rhuff/forecastfiles/categoryso4rv.pl line 18.
Global symbol "$total" requires explicit package name at /share/huina/rhuff/forecastfiles/categoryso4rv.pl line 18.
Execution of /share/huina/rhuff/forecastfiles/categoryso4rv.pl aborted due to compilation errors.
[rhuff@huina ~/forecastfiles]$


In other words, If I have the portion of the file shown below

08-01-2011 00:00:00 0.01 0.006
08-02-2011 00:00:00 0.13 0.036
08-03-2011 00:00:00 0.07 0.006
08-04-2011 00:00:00 0.06 0.026
08-06-2011 00:00:00 0.02 0.106
08-11-2011 00:00:00 0.01 0.016
08-13-2011 00:00:00 0.01 0.006
08-14-2011 00:00:00 0.00 0.006
08-18-2011 00:00:00 0.21 0.206
08-19-2011 00:00:00 0.01 0.206
08-20-2011 00:00:00 0.01 0.036
08-22-2011 00:00:00 0.02 0.026
08-23-2011 00:00:00 0.01 0.006
08-24-2011 00:00:00 0.01 1.26

The output file would look like this

1   4   1     25.0
2 13 12     92.3
3 12 12   100.0
4 13 13   100.0
5 14 14   100.0
6 14 14   100.0
ozo
Most Valuable Expert 2014
Top Expert 2015

Commented:
splain
/usr/bin/splain: Reading from STDIN
Global symbol "$total" requires explicit package name at /share/huina/rhuff/forecastfiles/categoryso4rv.pl line 12.
Global symbol "$total" requires explicit package name at
      /share/huina/rhuff/forecastfiles/categoryso4rv.pl line 12 (#1)
    (F) You've said "use strict" or "use strict vars", which indicates
    that all variables must either be lexically scoped (using "my" or "state"),
    declared beforehand using "our", or explicitly qualified to say
    which package the global variable is in (using "::").
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
I'm a little confused on what that means. How would a incorporate the as well as the new modification into the script and call the script form the command line? what is not explicit about the path I provided. Is the path in the command line the only mistake?

Author

Commented:
Ok. Im using the modified script below with different category levels as well as the suggestion you mentioned and got the error message below. What would the corrected script look like and/or what would be the correct way to call it in the command file using the script, input file, and output file specified above? I will be using this on different files so the files would preferable be called in the command line. It looks like though you want to hardcode the perl script path within the script itself? I am not clear on that.

use strict;

my @observed;
my @same;
while( <> ) {
   chomp;
   my($forecasted, $observed) = (split)[-2,-1];
   my $observedCategory = valueToCategory($observed);
   my $forecastedCategory = valueToCategory($forecasted);
   $observed[ $observedCategory ]++;
   $same[ $observedCategory ]++ if $observedCategory == $forecastedCategory;
   $total++;
}

foreach my $category(1..6) {
   my $observed   = $observed[$category]  || 0;
   my $same       = $same[$category]      || 0;
   printf("$category %3d %3d %5.1f\n", $total-$observed, $total-$same, $observed ? ($same*100)/$observed : 0);
}

sub valueToCategory {
   my($value) = @_;

   my $category;
   if( $value <= 15 )    { $category = 1 }
   elsif( $value <= 35.5 ) { $category = 2 }
   elsif( $value <=  65.5 ) { $category = 3 }
   elsif( $value <=  150.5 ) { $category = 4 }
   elsif( $value <=  250.5 ) { $category = 5 }
   else                  { $category = 6 }

   return $category;
}

Open in new window

Author

Commented:
error message above I should say listed in my initial follow up post
ozo
Most Valuable Expert 2014
Top Expert 2015

Commented:

use strict;

my @observed;
my @same;
my $total;

Author

Commented:
Ok. It almost worked but the columns in the output file seem reversed.The output file is below

1  37  92  52.6
2 117 137  44.4
3 153 153   0.0
4 153 153   0.0
5 153 153   0.0
6 152 153   0.0

It The second column in the output file should be the larger one since it the total number of times the condition was not met for column 4 of the input file. Column 3 of the output file is the total number of time the condition wasn't met for either column 3 * 4 for each row in the file..

Author

Commented:
I looked at the data file at it does not match the data.I used the updated script below on the attached file. The output is at the bottom.

updated script

use strict;

my @observed;
my @same;
my $total;
while( <> ) {
   chomp;
   my($forecasted, $observed) = (split)[-2,-1];
   my $observedCategory = valueToCategory($observed);
   my $forecastedCategory = valueToCategory($forecasted);
   $observed[ $observedCategory ]++;
   $same[ $observedCategory ]++ if $observedCategory == $forecastedCategory;
   $total++;
}

foreach my $category(1..6) {
   my $observed   = $observed[$category]  || 0;
   my $same       = $same[$category]      || 0;
   printf("$category %3d %3d %5.1f\n", $total-$observed, $total-$same, $observed ? ($same*100)/$observed : 0);
}

sub valueToCategory {
   my($value) = @_;

   my $category;
   if( $value <= 15 )    { $category = 1 }
   elsif( $value <= 35.5 ) { $category = 2 }
   elsif( $value <=  65.5 ) { $category = 3 }
   elsif( $value <=  150.5 ) { $category = 4 }
   elsif( $value <=  250.5 ) { $category = 5 }
   else                  { $category = 6 }

   return $category;
}

Open in new window

25knmergedebias3post.txt
Most Valuable Expert 2014
Top Expert 2015
Commented:
this reproduces the output for http:#36485182
use strict;

my @observed=(0)x7;
my @same=(0)x7;
my $total=0;
while( <> ) {
   chomp;
   my($forecasted, $observed) = (split)[-2,-1];
   my $observedCategory = valueToCategory($observed);
   my $forecastedCategory = valueToCategory($forecasted);
   $observed[ $observedCategory ]++;
   $same[ $forecastedCategory ]++ if $observedCategory != $forecastedCategory;
   $total++;
}

foreach my $category(1..6) {
   my $observed   = $total-$observed[$category];
   my $same       = $observed-$same[$category];
   printf("$category %3d %3d %5.1f\n", $observed, $same, $observed ? ($same*100)/$observed : 0);
}

sub valueToCategory {
   my($value) = @_;

   my $category;

   if( $value <= .1 )    { $category = 1 }
   elsif( $value <= .2 ) { $category = 2 }
   elsif( $value <=  1 ) { $category = 3 }
   elsif( $value <=  3 ) { $category = 4 }
   elsif( $value <=  5 ) { $category = 5 }
   else                  { $category = 6 }

   return $category;
}

Open in new window

Author

Commented:
It worked! Great! Thanks so much!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial