Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

making presence/absence table from a hash of arrays

by reubs85 (Acolyte)
on Sep 05, 2011 at 18:21 UTC ( #924283=perlquestion: print w/ replies, xml ) Need Help??
reubs85 has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

Please impart some Perl wisdom to a poor and pitiful Monkling...

Allow me to paint a simplistic picture of my conundrum: I have an array with (for arguments sake) 5 elements, thus:

one two three four five

And I have a hash where the keys are row numbers and the values are references to an array; this array having a varying number of elements that are equal to the headers in the table, but not necessarily in the same order, like so:

row_1 = one five two row_2 = four two row_3 = three one five four etc...

What I would dearly like is to print a table where each cell is filled with a 1/0 presence/absence binary, depending on if the column header in question is present in the array, thus for the hypothetical example above, we would get:

one two three four five row_1 = 1 1 0 0 1 row_2 = 0 1 0 1 0 row_3 = 1 0 1 1 1 etc...

Any tips or pointers would be massively appreciated,

Thanks very much!

Comment on making presence/absence table from a hash of arrays
Select or Download Code
Re: making presence/absence table from a hash of arrays
by Anonymous Monk on Sep 05, 2011 at 18:33 UTC

      Thanks for the responses everyone,

      Incidentally, it is not 'homework'; I am a PhD genome biologist still getting to grips with the finer details of Perl - I am going to use the code as part of a script that will allow me to count genes which are shared across different species. The example I wrote was merely for ease of readership.

      So whilst its true that I should learn more about the grep and map functions (although asking questions is part of learning, I think), I'm not skipping my way through some homework assignment.

      Thanks again!

        It is certainly possible to get a lot done without fancy map statements. There is certainly something to be said for doing something straightforward with foreach loops. Don't worry about being compact/terse - do something that is easy for you to understand - worry about more complex constructs when you are writing a lot more Perl.

        See code below. Perl is great at translating one thing into another thing - the hash table. So I just make a hash table table to translate the column name into an array index. This also perhaps could have been just statically declared, but I wanted to make this flexible. For each row in the table, I just zero out an array and use the name2Index translator to turn on the appropriate elements and then print that row.

        #!/usr/bin/perl -w use strict; use Data::Dump qw(pp); my $header_row= 'one two three four five'; my %table = ( row_1 => [qw(one five two)], row_2 => [qw(four two)], row_3 => [qw(three one five four)], ); my %name2Index; my $col=0; foreach my $col_head (split ' ',$header_row) { $name2Index{$col_head} = $col++; } print "name2Index table = ",pp(\%name2Index),"\n\n"; foreach my $row (sort keys %table) { my @bitmap = (0) x keys %name2Index; foreach my $col_name (@{$table{$row}}) { $bitmap[$name2Index{$col_name}] = 1; } print "$row = @bitmap\n"; } __END__ name2Index table = { five => 4, four => 3, one => 0, three => 2, two = +> 1 } row_1 = 1 1 0 0 1 row_2 = 0 1 0 1 0 row_3 = 1 0 1 1 1
Re: making presence/absence table from a hash of arrays
by jwkrahn (Monsignor) on Sep 05, 2011 at 19:58 UTC
    $ perl -le' my @array = qw/ one two three four five /; my %hash = ( row_1 => [ qw/ one five two / ], row_2 => [ qw/ four two / ], row_3 => [ qw/ three one five four / ], ); print "@array"; for my $key ( sort keys %hash ) { print "$key = ", join " ", map { my $elem = $_; grep( $_ eq $elem, + @{ $hash{ $key } } ) ? 1 : 0 } @array; } ' one two three four five row_1 = 1 1 0 0 1 row_2 = 0 1 0 1 0 row_3 = 1 0 1 1 1

      The grep can be simplified with a smart match:

      for my $key (sort keys %hash) { say "$key = ", join ' ', map $_ ~~ $hash{$key} ? 1 : 0, @array; }
Re: making presence/absence table from a hash of arrays
by Anonymous Monk on Sep 06, 2011 at 09:39 UTC

    You clearly want to use a regular expression:

    #!/ichigo/perl use v5.12; use warnings; use strict; my @array = qw/ one two three four five /; my %hash = ( row_1 => [ qw/ one five two / ], row_2 => [ qw/ four two / ], row_3 => [ qw/ three one five four / ], ); my $row = "@array"; say $row; for my $key (sort keys %hash) { my $re = join '|', @{$hash{$key}}; say "$key = ", grep s/\b($re)\b|\w+/$#-/g, "$row"; }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://924283]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2015-07-03 03:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (47 votes), past polls