Search code examples
pythonnumpynested-loops

How to avoid nested for loops in NumPy?


I have this code.

n_nodes = len(data_x)
X = np.zeros((n_nodes, n_nodes))

for i in range(n_nodes):
  for j in range(n_nodes):
    X[i, j] = data_x[i] ** j

I want to do the same task with no loops used at all. How can I do that with NumPy functions?


Solution

  • I'd suggest

    data_x[:,None]**np.arange(n_nodes)
    

    A check

    In [17]: data_x = np.array((3,5,7,4,6))
        ...: n_nodes = len(data_x)
        ...: X = np.zeros((n_nodes, n_nodes))
        ...: 
        ...: for i in range(n_nodes):
        ...:   for j in range(n_nodes):
        ...:     X[i, j] = data_x[i] ** j
        ...: print(X)
        ...: print('-----------')
        ...: print(data_x[:,None]**np.arange(n_nodes))
    [[1.000e+00 3.000e+00 9.000e+00 2.700e+01 8.100e+01]
     [1.000e+00 5.000e+00 2.500e+01 1.250e+02 6.250e+02]
     [1.000e+00 7.000e+00 4.900e+01 3.430e+02 2.401e+03]
     [1.000e+00 4.000e+00 1.600e+01 6.400e+01 2.560e+02]
     [1.000e+00 6.000e+00 3.600e+01 2.160e+02 1.296e+03]]
    -----------
    [[   1    3    9   27   81]
     [   1    5   25  125  625]
     [   1    7   49  343 2401]
     [   1    4   16   64  256]
     [   1    6   36  216 1296]]
    

    Some timing

    In [18]: %timeit data_x[:,None]**np.arange(n_nodes)
    2.18 µs ± 7.49 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
    
    In [19]: %%timeit
        ...: for i in range(n_nodes):
        ...:     for j in range(n_nodes):
        ...:         X[i, j] = data_x[i] ** j
    10.9 µs ± 107 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)