Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

PDL, applying function

by rootcho (Pilgrim)
on Aug 08, 2013 at 22:18 UTC ( [id://1048655]=perlquestion: print w/replies, xml ) Need Help??

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

hi,
Let say I have the following pdl :
$x = pdl(0,4,0,-3)

I want to do something like this (pseudo code):
for $el in $x if $el > 0 then $el = 1 if $el < 0 then $el = 0 if $el == 0 then $el = int(rand(9)) >= 5 ? 1 : 0 end

how do I do that.. (if I can, update the value inplace)

Replies are listed 'Best First'.
Re: PDL, applying function
by kevbot (Vicar) on Aug 09, 2013 at 07:16 UTC
    I believe that the code below modifies $x in place, but I'm not too familiar with the internals of PDL. There is a problem with the code below; for elements equal to 0, it will replace all of those elements with the same result...which may not be what you want.
    #!/usr/bin/env perl use strict; use warnings; use PDL; use PDL::NiceSlice; my $x = pdl(0,4,0,-3); print "Before: $x\n"; $x(which($x > 0)) .= 1; $x(which($x < 0)) .= 0; $x(which($x == 0)) .= int(rand(9)) > 5 ? 1: 0; print "After: $x\n"; exit;
    The code below will fix that problem, but you need to iterate through each element of the pdl:
    #!/usr/bin/env perl use strict; use warnings; use PDL; my $x = pdl(0,4,0,-3); print "Before: $x\n"; my $n = nelem($x); for ( my $i = 0; $i < $n; ++$i ) { my $val = $x->index($i); $val = $val > 0 ? 1 : $val < 0 ? 0 : $val == 0 ? (int(rand(9)) > 5 ? 1 : 0) : undef; $x->index($i) .= $val; } print "After: $x\n"; exit;
    By the way, you may find this node helpful: Processing values of a piddle (PDL) speedup using 'at' vs. 'index'. It's a discussion related to processing the elements of a pdl individually. In general, it's a good idea to avoid processing the elements individually (i.e. it's likely better if you can find a way to use the vector operations of PDL). If you can not avoid processing the elements individually, you may want to consider exporting the pdl to a perl array, performing some operations on the values of the array, and then creating a pdl from the result.

    I took a quick looked around for the pdl equivalent of the map command but I did not find one.

      thanks.. I found today similar solution to what you say .. i.e.:
      $x->where($x < 0) .= -1

      the link I already saw 2 days ago :)
      Can't figure out yet one-pass solution... but at least I dont have to make it array, loop over it and then reconstruct the piddle.
      thanks again
Re: PDL, applying function
by etj (Deacon) on May 22, 2022 at 01:36 UTC
    My approach would start from setting the zeroes to randomly 1 or 0 first, then using https://metacpan.org/pod/PDL::Primitive#clip (untested):
    $inds = $x->whichND($x == 0); $x->indexND($inds) .= ($x->random < 0.5)->indexND($inds); $x->inplace->clip(0,1);
    This would obviously benefit enormously from loop fusion or making your own custom PDL operation.

      clip is nice. I think first 2 lines can be shorter and more efficient: no need to generate possibly ginormous random array and then index into

      $view = $x->whereND($x == 0) $view .= $view->random < .5
        A great option! I'll confess I was a bit tired, so after figuring out something that would broadcast over n-dimensional inputs better than using where, I stopped. Your code is clearly better.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1048655]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-03-28 23:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found