开发者

how to create sequences with pdl?

I trying to translate part of my R code to perl with pdl, and I would like to know if pdl has any syntax for creating sequences (besides the trivial my $xx=pdl(1..20))

something like having a vector ['a','b'] rep 20 => a,b,a,b,a,b.... 20 times? [EDIT]: The basic repeats can be done with normal Perl repeat string 开发者_JAVA百科x operator but I am looking for something like the rep() and seq() in R:

[R]
> rep(1:3, each=2, times=3)
1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3
> rep(1:4, c(1,2,3,2))
1 2 2 3 3 3 4 4
> seq(0,12,3)
0 3 6 9 12


Well, I only just started using PDL but from what I've seen and used, it doesn't seem like PDL is really what you want for making sequences. You're probably better off using perl's range operator (..) with any combination of map, grep, and x.

That said, if you were really determined to use PDL for some reason, you could probably use the sequence function and then twiddle the piddle until it looks like what you want:

pdl> p sequence(10)

[0 1 2 3 4 5 6 7 8 9]


pdl> p sequence(2,4) #Slice column 1 for evens, 2 for odds.

[
 [0 1]
 [2 3]
 [4 5]
 [6 7]
]


pdl> p sequence(3,4) * 5 #Multiply to step by an amount.

[
 [ 0  5 10]
 [15 20 25]
 [30 35 40]
 [45 50 55]
]

You could also use slices to grab columns as a way to step along a sequence.

For anything else, such as what you're doing in your R examples, you'd need to start getting creative:

pdl> p $a = (yvals zeroes(2,3))+1

[
 [1 1]
 [2 2]
 [3 3]
]

pdl> p pdl($a,$a,$a)->flat #-> rep(1:3, each=2, times=3)
[1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3]

(The above would be shorter if I knew how to more easily duplicate matrixes) [edit] It seems that's easily done with dummy! $a = (zeroes(2,3)->yvals + 1)->dummy(2,3)->flat

Once again, unless you have a specific need to do this I think it would be best to use perl for making your sequences.

[edit]Here's how you'd do that: Note that 'x' is not just a string multiplier, it also multiplies lists. You need to explicitly use brackets around your vars to inform perl that x is being used on a list.

#> rep(1:3, each=2, times=3)
my @s = map {($_) x 2} (1..3) x 3;

#> seq(0,12,3)
my @s = map {$_ * 3} 0..12/3;

#> rep(1:4, c(1,2,3,2))
#Ewww. So you basically want to multiply one list by another list.
#Here's one way to do it:
use List::MoreUtils qw(pairwise);
my @s = &pairwise(sub {($a) x $b}, [1..4], [1,2,3,2])


I don't know about any PDL-specific syntax, but with Perl you can use the x operator to repeat elements of a list. Maybe

$xx = pdl(  ('a','b') x 20   );

would work.


PDL doesn't have seq() and rep() specifically but it does have constructors and the ability to manipulate and reshape multi-dimensional data.

Specifically, replicating sequences can be done by adding dummy dimensions of those sizes to the original data and then reshaping the result to 1-D.

Sequences with start:stop:stride can be generated by arithmetic operations on a sequence of integers which can be generated with the sequence() constructor.

Here are some PDL versions that correspond to the two R snippets from the original question with the comments explaining what the correspondences are:

pdl> pdl(1..3)                  # 1:3
$PDL1 = [1 2 3];

pdl> pdl(1..3)->(*2)->flat      # rep(1:3, each=2)
$PDL1 = [1 1 2 2 3 3];

pdl> pdl(1..3)->(,*3)->flat     # rep(1:3, times=3)
$PDL1 = [1 2 3 1 2 3 1 2 3];

pdl> pdl(1..3)->(*2,,*3)->flat  # rep(1:3, each=2, times=3)
$PDL1 = [1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3];

pdl> rld(pdl(2,1,5),pdl(1..3))  # rep(1:3, c(2,1,5))
$PDL1 = [1 1 2 3 3 3 3 3];


pdl> sequence(13)->(0:12:3)     # seq(0,12,3)
$PDL1 = [0 3 6 9 12];

Note the use of the rld, the run length decode command to perform the vector rep operation. It would be straightforward to implement the R routines using these sorts of index and dimension manipulation. Also, the above mostly work with integer index operations. If you need support for floating point numbers, you'll need to do something else.

See PDL::Basic for the sequence stuff and PDL::Slices for the index manipulations (PDL::NiceSlice is also relevant as that is the syntax used above). It is easy to try this sort of thing out to get working using one of the PDL shells: perldl or pdl2.

The PDL web site is at http://pdl.perl.org. For more discussions on PDL, please use the perldl mailing list for faster response by the PDL community at large.


As other people have said, it may be easier to do some of your examples using Perl and passing it to the pdl constructor. However the last example is easy enough:

$x = 3*xvals(5);
print $x; # [0 3 6 9 12]

After a little work, and not knowing R, I wonder if the question is well formed? I started assuming that the input to some new pdl_rep function would be a base piddle and then some repetition specification. However I started to doubt myself on what should it do when the base piddle was of higher dimension than a simple vector. Therefore I settled on 1D input only. Then I realized that as I and others have said, to do either the c or each type action one must break apart the base piddle and manipulate the elements at the Perl level and rebuild a piddle, or else do some silly dimension manipulation. The result of all this was that it seemed that the easiest way to build such a function was to have it be a pdl constructor itself.

Once this conclusion was reached, I realized that indeed building your piddle from well constructed map operations is what you intend to do. PDL is meant to benefit from the power of Perl, otherwise it would be a separate language. This rep function may not have been implemented by the designers because Perl already has it in spades.

Probably TL;DR, but I think your short answer is let your PDL use benefit from Perl too!


Here are some interesting things about the sequence() function and the matrix

$x = sequence(20)*2+1; ##odd
[1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39]
$x = sequence(20)*2;  ##even 
[0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38]
$x = sequence(20)%2; ## binary pattern
[0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
$x = sequence(20)%10  ## position matrix
[0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9]
$x = sequence(20)<=>10;  ## ray matrix
[-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 1 1 1 1 1 1 1 1]
$x = sequence(20)%4+2;  ## repeating pattern
[2 3 4 5 2 3 4 5 2 3 4 5 2 3 4 5 2 3 4 5]
$x = sequence(20)%6;  ##  notice how this is different 
[0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜