[Numpy-discussion] Inplace shift

Keith Goodman kwgoodman@gmail....
Tue Jun 10 09:08:31 CDT 2008


On Sat, Jun 7, 2008 at 6:48 PM, Anne Archibald
<peridot.faceted@gmail.com> wrote:
> 2008/6/7 Keith Goodman <kwgoodman@gmail.com>:
>> On Fri, Jun 6, 2008 at 10:46 PM, Anne Archibald
>> <peridot.faceted@gmail.com> wrote:
>>> 2008/6/6 Keith Goodman <kwgoodman@gmail.com>:
>>>> I'd like to shift the columns of a 2d array one column to the right.
>>>> Is there a way to do that without making a copy?
>>>>
>>>> This doesn't work:
>>>>
>>>>>> import numpy as np
>>>>>> x = np.random.rand(2,3)
>>>>>> x[:,1:] = x[:,:-1]
>>>>>> x
>>>>
>>>> array([[ 0.44789223,  0.44789223,  0.44789223],
>>>>       [ 0.80600897,  0.80600897,  0.80600897]])
>>>
>>> As a workaround you can use backwards slices:
>>>worki
>>> In [40]: x = np.random.rand(2,3)
>>>
>>> In [41]: x[:,:0:-1] = x[:,-2::-1]
>>>
>>> In [42]: x
>>> Out[42]:
>>> array([[ 0.20183084,  0.20183084,  0.08156887],
>>>       [ 0.30611585,  0.30611585,  0.79001577]])
>>
>> Neat. It makes sense to go backwards. Thank you.
>>
>>> Less painful for numpy developers but more painful for users is to
>>> warn them about the status quo: operations on overlapping slices can
>>> happen in arbitrary order.
>>
>> Now I'm confused. Could some corner case of memory layout cause numpy
>> to work from right to left, breaking the workaround? Or can I depend
>> on the workaround working with numpy 1.0.4?
>
> I'm afraid so. And it's not such a corner case as that: if the array
> is laid out in "C contiguous" order, you have to go backwards, while
> if the array is laid out in "FORTRAN contiguous" order you have to go
> forwards.

I think I'll end up using a code snippet like shift2:

def shift(x):
    x2 = x.copy()
    x[:,1:] = x2[:,:-1]
    return x

def shift2(x):
    if x.flags.c_contiguous:
        x[:,:0:-1] = x[:,-2::-1]
    elif x.flags.f_contiguous:
        x[:,1:] = x[:,:-1]
    else:
        raise ValueError, 'x must be c_contiguous or f_contiguous'
    return x

>> x = np.random.rand(2,3)
>> timeit shift(x)
100000 loops, best of 3: 5.02 µs per loop
>> timeit shift2(x)
100000 loops, best of 3: 4.75 µs per loop

>> x = np.random.rand(500,500)
>> timeit shift(x)
100 loops, best of 3: 2.51 ms per loop
>> timeit shift2(x)
1000 loops, best of 3: 1.62 ms per loop
>>
>> x = x.T
>>
>> timeit shift(x)
100 loops, best of 3: 4.17 ms per loop
>> timeit shift2(x)
1000 loops, best of 3: 348 µs per loop

f contiguous (x.T) is faster. How do I change an array from c
contiguous to f contiguous without changing the elements?


More information about the Numpy-discussion mailing list