Solved

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

Posted on 2011-09-04
11
434 Views
Last Modified: 2012-05-12
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
Comment
Question by:libertyforall2
  • 7
  • 4
11 Comments
 
LVL 84

Expert Comment

by:ozo
ID: 36483650
#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
 

Author Comment

by:libertyforall2
ID: 36485182
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
 
LVL 84

Expert Comment

by:ozo
ID: 36485194
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
VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

 

Author Comment

by:libertyforall2
ID: 36485427
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
 

Author Comment

by:libertyforall2
ID: 36485461
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
 

Author Comment

by:libertyforall2
ID: 36485462
error message above I should say listed in my initial follow up post
0
 
LVL 84

Expert Comment

by:ozo
ID: 36486706

use strict;

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

Author Comment

by:libertyforall2
ID: 36486771
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
 

Author Comment

by:libertyforall2
ID: 36486925
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
 
LVL 84

Accepted Solution

by:
ozo earned 500 total points
ID: 36487443
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
 

Author Closing Comment

by:libertyforall2
ID: 36487575
It worked! Great! Thanks so much!
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Update in Sql 7 37
ODBC Question 3 42
ServiceCenter IR Query Expressions 1 23
Access Importing Table Query With Specific Timestamp Daily 2 17
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
As technology users and professionals, we’re always learning. Our universal interest in advancing our knowledge of the trade is unmatched by most industries. It’s a curiosity that makes sense, given the climate of change. Within that, there lies a…
Video by: Steve
Using examples as well as descriptions, step through each of the common simple join types, explaining differences in syntax, differences in expected outputs and showing how the queries run along with the actual outputs based upon a simple set of dem…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

822 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question