将PDL分成两半

时间:2013-11-21 18:01:25

标签: perl pdl

我有一个一维PDL,我想对每一半进行计算;即分裂它,然后在前半部分进行计算,在下半部分进行相同的计算。

是否有一种更容易/更好/更优雅的方法来简单地将PDL分成两半而不是获得元素数量(使用nelem),将其除以两个,然后进行两次切片?

由于

1 个答案:

答案 0 :(得分:3)

是的,只要你不需要直接调用切片来获得你想要的东西。您可以使用以下内容链接splitdimdog

# Assume we have $data, a piddle
my ($left, $right) = $data->splitdim(0, $data->nelem/2)->dog;

当然,这很容易扩展到两个以上的部门。但是,如果你想将它扩展到更高维度的piddles(即所有存储在一个小提琴中的时间序列集合),你需要更加微妙。如果你想沿着第一个维度(索引为0)进行拆分,你可以这样说:

# Assume we have $data, a piddle
my ($left, $right) = $data->splitdim(0, $data->dim(0)/2)->mv(1, -1)->dog;

splitdim操作将第0维分为两个维,第0个长度为dim(0)/ 2,第1个长度为2(因为我们将其分为两个部分)。由于dog对最后一个维度进行操作,因此我们会在调用dog之前将第一维移动到结尾。

然而,即使使用一维解决方案,也有一个警告。由于$data->splitdim的工作方式,如果您有奇数个元素,它将截断最后一段数据。在21个元素的小提琴上尝试该操作,你会明白我的意思:

my $data = sequence(20);
say "data is $data";  # lists 0-19
my ($left, $right) = $data->splitdim(0, $data->nelem/2)->dog;
say "left is $left and right is $right";  # lists 0-9, then 10-19

$data = sequence(21);
say "data is $data";  # lists 0-20, i.e. 21 elements
my ($left, $right) = $data->splitdim(0, $data->nelem/2)->dog;
say "left is $left and right is $right";  # lists 0-9, then 10-19!!

如果你想避免这种情况,你可以生成自己的方法,将第一个维度分成两半而不截断。它可能看起来像这样:

sub PDL::split_in_half {
    my $self = shift;

    # the int() isn't strictly necessary, but should make things a
    # tad faster
    my $left = $self->slice(':' . int($self->dim(0)/2-1) );
    my $right = $self->slice(int($self->dim(0)/2) . ':');
    return ($left, $right);
}

在这里,我还使用内置的int来确保.5如果dim(0)是奇数,我们就没有my ($left, $right) = $data->split_in_half; 。这有点复杂,但是我们将这种复杂性完全掩盖在一个方法中,所以我们不必考虑复杂性,所以我们也可以在我们处理它的时候给自己买几个时钟周期。

然后你可以轻松地调用这个方法:

{{1}}