Как создать последовательности с PDL?
Я пытаюсь перевести часть моего R-кода в perl с помощью pdl, и я хотел бы знать, есть ли у pdl какой-либо синтаксис для создания последовательностей (кроме тривиального my $xx=pdl(1..20))
что-то вроде наличия вектора ['a','b'] rep 20 => a,b,a,b,a,b.... 20 раз?[РЕДАКТИРОВАТЬ]: Основные повторения могут быть сделаны с обычной строкой повторения Perl x
оператор, но я ищу что-то вроде rep() и seq() в 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
5 ответов
Ну, я только начал использовать PDL, но из того, что я видел и использовал, не похоже, что PDL действительно то, что вы хотите для создания последовательностей. Вы, вероятно, лучше использовать оператор диапазона Perl (..
) с любой комбинацией map
, grep
, а также x
,
Тем не менее, если вы действительно решили использовать PDL по какой-то причине, вы могли бы использовать sequence
Функцию, а затем вертеть piddle, пока он не будет выглядеть, как вы хотите:
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]
]
Вы также можете использовать фрагменты для захвата столбцов, чтобы пройти по последовательности.
Для чего-то еще, например, того, что вы делаете в своих примерах R, вам нужно начать проявлять креативность:
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]
(Выше было бы короче, если бы я знал, как проще дублировать матрицы)
[править] Кажется, что это легко сделать с помощью фиктивной фигуры!$a = (zeroes(2,3)->yvals + 1)->dummy(2,3)->flat
Еще раз, если у вас нет особой необходимости делать это, я думаю, что было бы лучше использовать Perl для создания ваших последовательностей.
[править] Вот как вы это сделаете:x
'не просто строковый множитель, он также умножает списки. Вы должны явно использовать скобки вокруг ваших переменных, чтобы сообщить Perl, что x
используется в списке.
#> 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])
Я не знаю ни о каком синтаксисе, специфичном для PDL, но с Perl вы можете использовать x
оператор для повторения элементов списка. Может быть
$xx = pdl( ('a','b') x 20 );
должно сработать.
PDL не имеет seq()
а также rep()
в частности, но у него есть конструкторы и возможность манипулировать и изменять многомерные данные.
В частности, репликация последовательностей может быть сделана путем добавления фиктивных измерений этих размеров к исходным данным и последующего преобразования результата в 1-D.
Последовательности с start:stop:stride могут быть сгенерированы арифметическими операциями над последовательностью целых чисел, которые могут быть сгенерированы конструктором sequence().
Вот некоторые версии PDL, которые соответствуют двум фрагментам R из исходного вопроса с комментариями, поясняющими, каковы соответствия:
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];
Обратите внимание на использование rld
команда декодирования длины пробега для выполнения вектора rep
операция. Было бы просто реализовать подпрограммы R, используя эти виды манипулирования индексами и измерениями. Кроме того, вышесказанное в основном работает с целочисленными индексными операциями. Если вам нужна поддержка чисел с плавающей запятой, вам нужно заняться чем-то другим.
Увидеть PDL::Basic
для последовательности вещей и PDL::Slices
для манипуляций с индексом (PDL::NiceSlice
также имеет значение, так как это синтаксис, использованный выше). Это легко попробовать, используя один из оболочек PDL: perldl
или же pdl2
,
Веб-сайт PDL находится по адресу http://pdl.perl.org/. Для получения дополнительной информации о PDL, пожалуйста, используйте список рассылки perldl для более быстрого ответа со стороны сообщества PDL.
Вот несколько интересных вещей о функции sequence() и матрице
$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]
Как говорили другие люди, может быть проще сделать некоторые из ваших примеров с использованием Perl и передать их pdl
конструктор. Однако последний пример достаточно прост:
$x = 3*xvals(5);
print $x; # [0 3 6 9 12]
После небольшой работы, не зная R, мне интересно, правильно ли сформулирован вопрос? Я начал предполагать, что вклад в какой-то новый pdl_rep
функция была бы базовой piddle, а затем некоторая спецификация повторения. Однако я начал сомневаться в том, что он должен делать, когда базовая опора имела более высокое измерение, чем простой вектор. Поэтому я остановился только на одномерном вводе. Тогда я понял, что, как я и другие говорили, чтобы сделать либо c
или же each
Действие типа: нужно разбить базовую опору и манипулировать элементами на уровне Perl и перестроить опору, либо выполнить глупую манипуляцию с размерами. Результатом всего этого было то, что казалось, что самый простой способ построить такую функцию - это иметь сам конструктор pdl.
Когда я пришел к такому выводу, я понял, что на самом деле сборка вашего piddle из хорошо сконструированных картографических операций - это то, что вы намерены делать. Предполагается, что PDL использует преимущества Perl, в противном случае это будет отдельный язык. это rep
Возможно, эта функция не была реализована дизайнерами, потому что в Perl она уже есть.
Вероятно, TL;DR, но я думаю, что ваш краткий ответ таков: пусть ваш PDL использует преимущества Perl!