-6

arr is a n-dimensional numpy array.

How to change sign of every element of arr with an odd sum of indices?

For example, arr[0, 1, 2] needs a sign change because it has a sum of indices 0 + 1 + 2 = 3, which is odd.

When I convert arr to a list, I notice that every second element in the list are elements that needs a sign change.

Another example:

Original array:

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

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]

Array with signs changed:
[[[ 0  -1  2]
  [ -3  4  -5]
  [ 6  -7  8]]

 [[ -9 10 -11]
  [12 -13 14]
  [-15 16 -17]]

 [[18 -19 20]
  [-21 22 -23]
  [24 -25 26]]]
R zu
  • 2,034
  • 12
  • 30

2 Answers2

1

np.negative is silghtly faster than multiplying (as it is a ufunc)

N = 5
arr = np.arange(N ** 3).reshape(N, N, N)
%timeit arr.ravel()[1::2] *= -1
%timeit np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2])

The slowest run took 8.74 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 3.39 µs per loop
The slowest run took 5.57 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 3.12 µs per loop

N = 25
arr = np.arange(N ** 3).reshape(N, N, N)
%timeit arr.ravel()[1::2] *= -1
%timeit np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2])

The slowest run took 7.03 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 10.8 µs per loop
The slowest run took 5.27 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 8.63 µs per loop

N = 101
arr = np.arange(N ** 3).reshape(N, N, N)
%timeit arr.ravel()[1::2] *= -1
%timeit np.negative(arr.ravel()[1::2], out = arr.ravel()[1::2])

1000 loops, best of 3: 663 µs per loop
1000 loops, best of 3: 512 µs per loop
Daniel F
  • 13,620
  • 2
  • 29
  • 55
0

Greatly simplified by hpaulj's suggestion.

Program:

import numpy as np


def change_sign(arr):
    """Switch sign of every second element of arr in-place
    Note
    ----
    Modifies the input array (arr).
    """
    # arr.reshape(-1) makes a 1D view of arr
    #
    # [1::2] select every other element of arr,
    #   starting from the 1st element.
    #
    # *= -1 changes sign of selected elements.

    arr.reshape(-1)[1::2] *= -1
    return arr


def main():
    N = 3
    arr = np.arange(N ** 3).reshape(N, N, N)
    print("original array:")
    print(arr)
    print("change signs")
    print(change_sign(arr))


main()

Result:

original array:
[[[ 0  1  2]
  [ 3  4  5]
  [ 6  7  8]]

 [[ 9 10 11]
  [12 13 14]
  [15 16 17]]

 [[18 19 20]
  [21 22 23]
  [24 25 26]]]
change signs
[[[  0  -1   2]
  [ -3   4  -5]
  [  6  -7   8]]

 [[ -9  10 -11]
  [ 12 -13  14]
  [-15  16 -17]]

 [[ 18 -19  20]
  [-21  22 -23]
  [ 24 -25  26]]]
R zu
  • 2,034
  • 12
  • 30