1

If I have a MxN numpy array denoted arr, I wish to index over all elements and adjust the values like so

for m in range(arr.shape[0]):
    for n in range(arr.shape[1]):
        arr[m, n] += x**2 * np.cos(m) * np.sin(n)

Where x is a random float.

Is there a way to broadcast this over the entire array without needing to loop? Thus, speeding up the run time.

2
  • You could do an "inline" for something like this if you were using a function [return x+i for x in lst] But dont know how else you would access elements without a for loop. Commented Feb 22, 2022 at 14:09
  • 1
    You could but does it makes sense? np.cos(2*pim) * np.sin(2*pin) is equal to 0 as it is just multiples of 2*pi Commented Feb 22, 2022 at 14:18

3 Answers 3

1

You are just adding zeros, because sin(2*pi*k) = 0 for integer k.

However, if you want to vectorize this, the function np.meshgrid could help you. Check the following example, where I removed the 2 pi in the trigonometric functions to add something unequal zero.

x = 2
arr = np.arange(12, dtype=float).reshape(4, 3)
n, m = np.meshgrid(np.arange(arr.shape[1]), np.arange(arr.shape[0]), sparse=True)
arr += x**2 * np.cos(m) * np.sin(n)
arr

Edit: use the sparse argument to reduce memory consumption.

Sign up to request clarification or add additional context in comments.

Comments

0

You can use nested generators of two-dimensional arrays:

import numpy as np
from random import random

x = random()
n, m = 10,20
arr = [[x**2 * np.cos(2*np.pi*j) * np.sin(2*np.pi*i) for j in range(m)] for i in range(n)]

Comments

0
In [156]: arr = np.ones((2, 3))

Replace the range with arange:

In [157]: m, n = np.arange(arr.shape[0]), np.arange(arr.shape[1])

And change the first array to (2,1) shape. A (2,1) array broadcasts with a (3,) to produce a (2,3) result.

In [158]: A = 0.23**2 * np.cos(m[:, None]) * np.sin(n)
In [159]: A
Out[159]: 
array([[0.        , 0.04451382, 0.04810183],
       [0.        , 0.02405092, 0.02598953]])
In [160]: arr + A
Out[160]: 
array([[1.        , 1.04451382, 1.04810183],
       [1.        , 1.02405092, 1.02598953]])

The meshgrid suggested in the accepted answer does the same thing:

In [161]: np.meshgrid(m, n, sparse=True, indexing="ij")
Out[161]: 
[array([[0],
        [1]]),
 array([[0, 1, 2]])]

This broadcasting may be clearer with:

In [162]: m, n
Out[162]: (array([0, 1]), array([0, 1, 2]))
In [163]: m[:, None] * 10 + n
Out[163]: 
array([[ 0,  1,  2],
       [10, 11, 12]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.