Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 448
  • Last Modified:

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

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
0
libertyforall2
Asked:
libertyforall2
  • 7
  • 4
1 Solution
 
ozoCommented:
#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);
}
0
 
libertyforall2Author 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
0
 
ozoCommented:
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 "::").
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
libertyforall2Author 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?
0
 
libertyforall2Author 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

0
 
libertyforall2Author Commented:
error message above I should say listed in my initial follow up post
0
 
ozoCommented:

use strict;

my @observed;
my @same;
my $total;
0
 
libertyforall2Author 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..
0
 
libertyforall2Author 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
0
 
ozoCommented:
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

0
 
libertyforall2Author Commented:
It worked! Great! Thanks so much!
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 7
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now