1

I have this function:

def fun(x):   # x is a vector with size: (size_x*size_y) = n 
    c = 0
    f_vec = np.zeros((size_x*size_y))


    for i in range(size_x):
        for j in range(size_y):
             f_vec[c]=i*j*x[c]   
             c=c+1

    return f_vec

I do this because what happens is that the vector x is (considering size_x=4 and size_y=3)

 x[0]=x00    #c=0  i=0,j=0
 x[1]=x01    #c=1  i=0, j=1
 x[2]=x02    #c=2   i=0. j=size_y-1
 x[3]=x10    #c=3   i=1, j=0
 x[4]=x11
  ...
 x[n]=x32    #c=n   i=size_x-1, j= size_y-1

Can I avoid the nested loop and do a simple vector operation? I would like to have something like f[c] = F[x[c]] *i *j

But it is not that simple to find i and j by knowing the c value. Do you know a way?

Thanks.

AA10
  • 207
  • 1
  • 7

2 Answers2

2

You can use broadcasting for this:

(
    x.reshape(size_x, size_y) *
    np.arange(size_x)[:, None] *
    np.arange(size_y)
).ravel()

or Einstein Summation form

np.einsum(
    'ij,i,j->ij',
    x.reshape(size_x, size_y),
    np.arange(size_x),
    np.arange(size_y)
).ravel()
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
  • This is will not work for more complex functions, will it? Suppose that instead of simply return i*j, you have conditionals and other variables that depend on i and j. Can I have access to the value of i and j for each calculation? – AA10 Dec 10 '19 at 20:28
  • Depends ;-) just open another question with a code snippet that shows what you're trying to do – Nils Werner Dec 10 '19 at 21:24
  • I have created a new question. This is the link: [link](https://stackoverflow.com/questions/59295699/python3-vectorizing-nested-loop-with-conditionals-and-functions) – AA10 Dec 11 '19 at 23:38
1

Essentially, this is the same as Nils Werner's answer, but I find it easier to understand the i*j part as the 2D ndarray np.outer(np.arange(x_size), np.arange(y_size), and then do broadcasting:

(x.reshape(x_size, y_size) * np.outer(np.arange(x_size), np.arange(y_size)).ravel()

You can pre-calculate the i*j part if you're doing this repeatedly for the same values of x_size and y_size.

mtrw
  • 34,200
  • 7
  • 63
  • 71