CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Post deleted by cluna

 



cluna
Novice

Mar 17, 2013, 7:48 AM

Post #1 of 16 (1283 views)
Post deleted by cluna

 


Laurent_R
Veteran / Moderator

Mar 17, 2013, 9:27 AM

Post #2 of 16 (1270 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

Hi,

line 19, you have this:


Code
my $value = my $hash{$IDp[$i][1]};


The "my" on the right side of the = operator is obviously wrong.

The "my" operator is used to declare a new variable, and you cannot have a new variable on the right side of an = operator.

Having said that, removing the "my" may remove this syntax error message, but your program is not going to work any better, since $hash{$IDp[$i][1]} does not make any sense.

From your previous code, @IDp is an array containing the words of your input line, it will not magically become an hash.

If you need to capture the second and fifth colum of your line, you can just do this:


Code
my (value2col, $value5col) = ($IDp[1], $IDp[4]);

or, simpler:


Code
my (value2col, $value5col) = @IDp[1, 4];


Or, if you want to use these two values as a key/value pair to populate a new hash:


Code
$region_ID{$IDp[1]} = $IDp[4];



hwnd
User

Mar 17, 2013, 9:39 AM

Post #3 of 16 (1266 views)
Re: [Laurent_R] Syntax Errors In Program With Hash [In reply to] Can't Post

I would just use something likes this referencing a hash of hashes.


Code
  

my @data;

foreach my $item ( @txtfiles ) {

open my $fh, '<', $item or die $!;
while (<$fh>) {
my %rec;

my @cols = qw(col1 col2 col3 col4 col5 col6);
@rec{@cols} = split /\s+/;

push @data, \%rec;
}
close $fh;

for my $key (sort { $a->{col1} <=> $b->{col1} } @data) {

...

print out of $key{col1}, $key{col2} and so on..

...

}
}



Kenosis
User

Mar 17, 2013, 10:02 AM

Post #4 of 16 (1264 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

The situation you're describing calls for a hash of arrays (HoA), where the key is the region and its associated value is a reference to a list of p-values. Consider the following option:

Code
use strict; 
use warnings;

my ( $numFiles, %hash );

for my $file (<*.txt>) {
open my $fh, '<', $file or die $!;

while (<$fh>) {
my ( $region, $pValue ) = (split)[ 1, 4 ];
push @{ $hash{$region} }, $pValue;
}
close $fh;
$numFiles++;
}

for my $region ( sort keys %hash ) {
if ( @{ $hash{$region} } == $numFiles ) {
print "$region\t" . ( join "\t", @{ $hash{$region} } ) . "\n";
}
}


As you have, a file glob is used to get a listing of the current dir's *.txt files. Each file is processed using the three-argument form of open. Each file line (in Perl's default scalar) is split and sliced to grab only the region and p-value entries. Then the p-value is pushed onto the list that's keyed by region. A variable that counts the number of files is finally incremented.

Using your region/p-value dataset example, the hash structure would look like the following:

Code
$VAR1 = { 
'np1000056' => [
'0.45',
'0.14',
'0.5'
]
};


Thus, each region, as key, would be associated with a list of p-values. The next step is to (selectively) print these, and that's what occurs within the last for.

The last segment sorts the keys, and then evaluates whether the number of items in the list associated to the region via a reference is equal to the number of files (i.e., whether there is an associated p-value for each file). If so, it prints the key and those values as a tab-delimited line.

To save the output to a file, you can do the following from the command line:

perl script.pl >resultsFile

The second argument just directs output to a file. Without it, the results are printed to the screen.

This has been tested, but let me know if you encounter any issues or have any questions.

Hope this helps!

PS - My compliments on your clearly-articulated specs and problem, and your use of strict and warnings at the top of your script.


(This post was edited by Kenosis on Mar 17, 2013, 10:19 AM)


hwnd
User

Mar 17, 2013, 10:08 AM

Post #5 of 16 (1260 views)
Re: [Kenosis] Syntax Errors In Program With Hash [In reply to] Can't Post

My fault, I overlooked him having an array object as well ;)


Laurent_R
Veteran / Moderator

Mar 17, 2013, 10:23 AM

Post #6 of 16 (1254 views)
Re: [Laurent_R] Syntax Errors In Program With Hash [In reply to] Can't Post

Hi,

after having given my previous answer, I thought that you might actually have wanted to populate an array of hashes (one hash per input file) or possibly an hash of arrays. So, I thought, as soon as I get back to the computer, I'll improve my answers to better fit your needs.

Even though other answers have been given in between, I'll modify my answer to populate an AoH:


Code
$region_ID[$i]{$IDp[1]} = $IDp[4];



cluna
Novice

Mar 17, 2013, 12:55 PM

Post #7 of 16 (1243 views)
Re: [Kenosis] Syntax Errors In Program With Hash [In reply to] Can't Post

Kenosis, I haven't tested the script, but I will soon. Thank you for your post, especially with explaining the setup/commands. I have never used a variable file handle. Could you please explain to me the purpose of $fh?


(This post was edited by cluna on Mar 17, 2013, 1:15 PM)


Kenosis
User

Mar 17, 2013, 1:06 PM

Post #8 of 16 (1237 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

You're most welcome, cluna!

It's best to avoid using global variables, and barewords as file handles qualify as such. Instead, lexically-scoped variables, i.e., those preceded with my, are preferred. Thus, we see such articles as Always use the three-argument open.


hwnd
User

Mar 17, 2013, 1:07 PM

Post #9 of 16 (1236 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

Using a filehandle variable allows you to pass it to or return it from a function, store in a structure, ...

Check out Difference between dynamic and lexical scoping


cluna
Novice

Mar 17, 2013, 1:59 PM

Post #10 of 16 (1229 views)
Re: [hwnd] Syntax Errors In Program With Hash [In reply to] Can't Post

Thank you for your responses, hwnd.


Kenosis
User

Mar 17, 2013, 2:50 PM

Post #11 of 16 (1224 views)
Re: [hwnd] Syntax Errors In Program With Hash [In reply to] Can't Post

Using a filehandle variable allows you to pass it to or return it from a function, store in a structure, ...

A bareword file handle (reference) also allows these.

Passing a bareword file handle reference:


Code
use strict; 
use warnings;

readData( \*DATA );

sub readData {
my ($fh) = @_;

while (<$fh>) {
print;
}
}

__DATA__
This is some
Data that can be read
By passing a handle


Returning a bareword file handle reference:


Code
use warnings; 
use strict;

my $fh = getHandle();

while (<$fh>) {
print;
}

sub getHandle {
return \*DATA;
}

__DATA__
This is some
Data that can be read
By passing a handle


Storing a bareword file handle reference in a structure:


Code
use warnings; 
use strict;
use IO::File;

my %hash;

handleInHash(\%hash);

while (my $line = $hash{data}->getline) {
print $line;
}

sub handleInHash {
my ($hash_ref) = @_;
$$hash_ref{data} = \*DATA;
}

__DATA__
This is some
Data that can be read
By passing a handle


Output of all three:


Code
This is some 
Data that can be read
By passing a handle


The issue here is that bareword file handles are global, whereas lexically-scoped variables are not. For example:


Code
{ 
open FILE, '<', 'data.txt' or die $!;
}

my $line = <FILE>;
print $line;
close FILE;


works to read one line of the file data.txt--even though the bareword FILE was initialized within a code block--because FILE is global. However, the following:


Code
{ 
open my $FILE, '<', 'data.txt' or die $!;
}

my $line = <$FILE>;
print $line;
close $FILE;


doesn't work, because the value of $FILE is scoped within its code block, i.e., it's not global.

Using global variables can create some very problematic issues, so using my is encouraged...


(This post was edited by Kenosis on Mar 17, 2013, 3:22 PM)


cluna
Novice

Mar 17, 2013, 5:51 PM

Post #12 of 16 (1209 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

Given a hash of arrays, how can you define mathematical operations with the list of p-values? For example, how could you calculate the mean of the p-values for each key (or reef regionID)?

Thanks again, Kenosis, for posting examples regarding use of "my."


(This post was edited by cluna on Mar 17, 2013, 5:58 PM)


Chris Charley
User

Mar 17, 2013, 6:40 PM

Post #13 of 16 (1200 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

Not sure how you identify a region as a 'reef ' region, but here is a way assuming that 'reef' makes up part of the key- you have to determine what a reef region key is.


Code
use List::Util qw/ sum /; 

for my $region ( sort keys %hash ) {
if ($region =~ /reef/) { # Or, however you identify a 'reef' region
my $avg = sum( @{ $hash{$region} }) / @{ $hash{$region} };
}
}



cluna
Novice

Mar 17, 2013, 6:51 PM

Post #14 of 16 (1196 views)
Re: [Chris Charley] Syntax Errors In Program With Hash [In reply to] Can't Post

Thank you, Chris Charley. What does the line "use List::Util qw/ sum /;" refer to?

(The key's full name is coral reef regionID, but "region" is used for short is identifying the key. I'm sorry for any misunderstandings.)


(This post was edited by cluna on Mar 17, 2013, 7:02 PM)


Chris Charley
User

Mar 17, 2013, 7:01 PM

Post #15 of 16 (1190 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

That imports the `sum` function from the List::Util module. (`sum` is used in the formula to find the average of the p-values)

Code
 my $avg = sum( @{ $hash{$region} }) / @{ $hash{$region} };


This takes the sum of the p-values array, @{ $hash{$region} ) and divides the sum by the number of p-values in the array, @{ $hash{$region} }

sum puts it's argument in list context and the division puts the array in scalar context (or the number of p-values).


(This post was edited by Chris Charley on Mar 17, 2013, 7:07 PM)


Kenosis
User

Mar 17, 2013, 7:01 PM

Post #16 of 16 (1189 views)
Re: [cluna] Syntax Errors In Program With Hash [In reply to] Can't Post

You're most welcome, again!

Using the last for loop from above, you could do the following to get the mean for each region:


Code
for my $region ( sort keys %hash ) { 
if ( @{ $hash{$region} } == $numFiles ) {
my $sum;

my $pValueCount = @{ $hash{$region} };
$sum += $_ for @{ $hash{$region} };
my $mean = sprintf "%.2f", $sum / $pValueCount;

print "$region\t" . ( join "\t", @{ $hash{$region} } ) . "\n";
print "mean: $mean\n\n";
}
}


Sample output:


Code
np1000056	0.50	0.37	0.77	0.67 
mean: 0.58


Think of the p-values being stored in a 'keyed' array, and then treat that array as you would any other. The following:


Code
$sum += $_ for @{ $hash{$region} };


sums all the values in that array, and the next line uses sprintf to format the output.

In the example above,


Code
my $pValueCount = @{ $hash{$region} };


was used to obtain the element count of the array--even though we could have just used $numFiles.


(This post was edited by Kenosis on Mar 17, 2013, 11:35 PM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives