roark has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I have implemented the following code with using a loop. I tried avoiding the loop by where, which functions but did not have any luck.
The code is as follows:
$dec = pdl [[1,1,2,2,2],[10,15,13,11,4]]; my $min = $dec->(:,0) ->minimum; my $max = $dec->(:,0) ->maximum; print $max,"fwe\n"; $v = zeroes(2,2); $v(0,0) .= $min; $v(0,1) .= $max; for (my $i =$min; $i< 3; $i++) { $v(1,$i-1) .= $dec->(:,1)-> index(which $dec->(:,0) eq $i)->maximu +m; }
I am hoping via a single function, threading will be much faster. Seeking wisdom, any help appreciated

Replies are listed 'Best First'.
Re: PDL threading where/which instead of loop
by BrowserUk (Patriarch) on Aug 18, 2013 at 19:42 UTC

    Do you think this  $dec->(:,0) ->minimum; is legal perl?

    Because I get: syntax error at ..., near "(:"


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      It works for me, can be due to NiceSlice
      use PDL; use PDL::NiceSlice;

        Okay. NiceSlice is a source code filter which explains how it can 'undo' a syntax error. Sorry to have bothered you :)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: PDL threading where/which instead of loop
by kevbot (Vicar) on Aug 19, 2013 at 03:54 UTC
    I'm not sure I understand your requirements. What are the potential contents of the $dec pdl? Will the values of the elements in $dec(:,0) always be 1 or 2? Are you essentially trying to accomplish this:
    #!/usr/bin/env perl use strict; use warnings; use PDL; use PDL::NiceSlice; my $dec = pdl [[1,1,2,2,2],[10,15,13,11,4]]; my $min = $dec->(:,0)->minimum; my $max = $dec->(:,0)->maximum; my $v = zeroes(2,2); $v(0,0) .= $min; $v(0,1) .= $max; $v(1,0) .= $dec->(:,1)->index(which $dec->(:,0) eq $v(0,0))->maximum; $v(1,1) .= $dec->(:,1)->index(which $dec->(:,0) eq $v(0,1))->maximum; print "$v\n"; exit;
    Which results in this output:
    [ [ 1 15] [ 2 13] ]
    Are you trying to find a way to construct $v as a pdl directly without defining the individual elements of $v? I have a hunch that this may be a case of an XY Problem.
      Sorry for not being clear. The values of $dec(:,0) will not be always 0 or 1. In fact they can take any number of values(from 1 to some maximum number), my goal is to compute -for each unique value - the maximum of corresponding values in $dec(:,1).
      Thus
      $dec = pdl [[1,1,2,2,3],[10,15,13,11,6]];

      I want the output to be:
      [ [ 1 15] [ 2 13] [ 3 6] ]
      Hope this helps, thanks in advance..
        Here is one way to achieve this without constructing a loop that iterates over each element of the pdl. I'm not sure that this would be significantly faster than just iterating over the elements of the pdl...you would need to benchmark it (also you may want to consider comparing it to a plain-perl solution).
        #!/usr/bin/env perl use strict; use warnings; use PDL; use PDL::NiceSlice; my $dec = pdl [[1,1,2,2,3],[10,15,13,11,6]]; my $groups_vec = $dec(:,0); my $groups = $groups_vec->uniq; my $groups_t = $groups->transpose; my $values = $dec(:,1); my $masks = ($groups_t == $groups_vec); my $group_values = $masks*$values; my $max_of_each_group = $group_values->maximum; my $final_pdl = pdl($groups, $max_of_each_group)->transpose; print "Original Data: $dec\n"; print "Groups: $groups\n"; print "Transposed Groups: $groups_t\n"; print "Masks: $masks\n"; print "Group values: $group_values\n"; print "Max of each group: $max_of_each_group\n"; print "Final pdl: $final_pdl\n"; exit;
        Gives the following output:
        Original Data: [ [ 1 1 2 2 3] [10 15 13 11 6] ] Groups: [1 2 3] Transposed Groups: [ [1] [2] [3] ] Masks: [ [1 1 0 0 0] [0 0 1 1 0] [0 0 0 0 1] ] Group values: [ [10 15 0 0 0] [ 0 0 13 11 0] [ 0 0 0 0 6] ] Max of each group: [15 13 6] Final pdl: [ [ 1 15] [ 2 13] [ 3 6] ]