Solved

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

Posted on 2011-09-04
11
432 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
Comment Utility
#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
Comment Utility
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
Comment Utility
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
 

Author Comment

by:libertyforall2
Comment Utility
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
Comment Utility
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

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

Expert Comment

by:ozo
Comment Utility

use strict;

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

Author Comment

by:libertyforall2
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
It worked! Great! Thanks so much!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
MS Access question 11 46
microsoft access question 8 44
Need way to extend view in MS Access 47 63
Mysql not caching queries 4 45
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
SQL Command Tool comes with APEX under SQL Workshop. It helps us to make changes on the database directly using a graphical user interface. This helps us writing any SQL/ PLSQL queries and execute it on the database and we can create any database ob…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
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…

728 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now