Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Find column number for the row-wise max value

by jaksow (Initiate)
on Feb 29, 2012 at 15:48 UTC ( #956961=perlquestion: print w/ replies, xml ) Need Help??
jaksow has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I'm quite new to Perl and would like to ask: How do I retrieve, row-wise, the column number of the entry that has the largest value?
For example, let's say that I have the following dataset:

row_id;value1;value2;value3
id001;10;10;30
id002;30;20;50
id003;30;80;10

I then want my code to return:
3
3
2

because these are the column numbers that correspond to the column which contain the row-wise maximum.

Thank you!

Comment on Find column number for the row-wise max value
Re: Find column number for the row-wise max value
by JavaFan (Canon) on Feb 29, 2012 at 15:58 UTC
    Untested code:
    my @max; for (my $n = 0; $n < @lines; $n++) { # Assume the rows are in @lines $values[$n] = [split /;/, $lines[$n]]; shift @values; for (my $i = 0; $i < @{$values[0]}; $i++) { if ($values[$i] >= $lines[$max[$i]||0][$i]) { $max[$i] = $n; } } } print "$_\n" for @max;
Re: Find column number for the row-wise max value
by LanX (Canon) on Feb 29, 2012 at 16:10 UTC
    Just for fun with Schwartzian transform and expensive sort!

    DB<109> $txt='id003;30;80;10' DB<110> local $.=0; @sort = sort {$a->[0] <=> $b->[0]} map { [$_ => +$.++] } split /;/, $txt DB<111> print $sort[-1]->[1] 2

    Was to lazy to eliminate the id field first. :)

    Cheers Rolf

Re: Find column number for the row-wise max value
by ashokpj (Hermit) on Feb 29, 2012 at 16:53 UTC

    This code may give idea to you

    my @a = (1,23,451,289,5); my @b = (341,561,5,67,78,891); &func( \@a); &func (\@b); sub func(){ my @myarray = @{$_[0]}; my $max; my $index; my $x = 0; for ( @myarray ) { if (!defined $max or $_ > $max ){ $index = $x ; $max = $_; } $x++; } print "The greatest is element number $index: $myarray[$index]\n"; }

    Output

    The greatest is element number 2: 451

    The greatest is element number 5: 891

Re: Find column number for the row-wise max value
by ikegami (Pope) on Feb 29, 2012 at 18:39 UTC

    Lists all columns that have the highest in the event of a tie (e.g. id004;10;30;30)

    use strict; use warnings; use feature qw( say ); use List::Util qw( max ); <>; while (<>) { chomp; my @fields = split /;/; my %indexes; push @{ $indexes{ $fields[$_] } }, $_ for 1..$#fields; say join ",", @{ $indexes{ max keys %indexes } }; }

    As a "one liner":

    perl -MList::Util=max -F\; -lanE' BEGIN { <> } my %indexes; push @{ $indexes{ $F[$_] } }, $_ for 1..$#F; say join ",", @{ $indexes{ max keys %indexes } }; '
Re: Find column number for the row-wise max value
by mcdave (Beadle) on Feb 29, 2012 at 19:59 UTC
    In English, not Perl, you'd do it by:
    • For each line in the input,
      • Split the line into its pieces, separating the row ID from the data,
      • Assume the first is the biggest,
      • Walk down the indices, keeping track of which represents the largest, and
      • Report that answer
    But Perl can look a lot like English if you stare at it for long enough:
    foreach my $l (@line) { my ($row_id, @row_data) = split( /;/, $l ) ; my $idx = 0 ; do { $idx = $_ if $row[$_] > $row[$idx] } for 1..$#row_data ; print (1+$idx), "\n" ; }
    but there's lots of ways to do it.
Re: Find column number for the row-wise max value
by Tux (Monsignor) on Mar 01, 2012 at 10:43 UTC

    Looks like that data is CSV (with a M$ sep_char). You could/should switch to a real CSV reader when the data is actually more complicated than your example snippet. The de-facto modules to parse CSV are Text::CSV_XS and Text::CSV. If the data is more complicated, you could also turn to using DBD::CSV and hit the data with SQL statements.


    Enjoy, Have FUN! H.Merijn
Re: Find column number for the row-wise max value
by Marshall (Prior) on Mar 02, 2012 at 06:36 UTC
    Another way using the reduce() function in List::Util. List:Util is a core module so you don't have to install it. If more than one "max", prints the first one.
    #!/usr/bin/perl -w use strict; use List::Util qw(reduce); while (<DATA>) { chomp; my (@array) = split';',$_; my $ColumnNumber = reduce { $array[$a] >= $array[$b] ? $a : $b } 1..@array-1; print $ColumnNumber, "\n"; } =prints 3 3 2 =cut __DATA__ id001;10;10;30 id002;30;20;50 id003;30;80;10
Re: Find column number for the row-wise max value
by vagabonding electron (Hermit) on Mar 02, 2012 at 09:16 UTC
    My first attempt to answer a question :-)
    just with the Perl elements I know so far.
    use strict; use warnings; my $header = <DATA>; while (my $line = <DATA> ) { chomp $line; my @array = split /;/, $line, -1; my $row_id = shift @array; my @sorted = sort {$b<=>$a} @array; my $max = shift @sorted; my @index = map {$_ + 1} grep { $array[$_] eq $max } 0..$#array; print "Max value in the row $row_id is $max "; print "in the column(s) ", @index > 1 ? join ',', @index : @index +, ".\n"; } __DATA__ row_id;value1;value2;value3 id001;10;10;30 id002;30;20;50 id003;30;80;10 id004;30;90;90 id005;50;50;10
    This prints:
    Max value in the row id001 is 30 in the column(s) 3. Max value in the row id002 is 50 in the column(s) 3. Max value in the row id003 is 80 in the column(s) 2. Max value in the row id004 is 90 in the column(s) 2,3. Max value in the row id005 is 50 in the column(s) 1,2.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (12)
As of 2014-08-01 17:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Who would be the most fun to work for?















    Results (36 votes), past polls