Link to home
Start Free TrialLog in
Avatar of libertyforall2
libertyforall2Flag for United States of America

asked on

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

IN my original post https://www.experts-exchange.com/questions/27283111/Parsing-data-using-excel-or-perl-Finding-a-percent-value-for-values-in-a-certain-range-with-three-columns.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
Avatar of ozo
ozo
Flag of United States of America image

#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);
}
Avatar of libertyforall2

ASKER

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
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 "::").
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?
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

error message above I should say listed in my initial follow up post

use strict;

my @observed;
my @same;
my $total;
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..
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
ASKER CERTIFIED SOLUTION
Avatar of ozo
ozo
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
It worked! Great! Thanks so much!