In [41]: two_at = 2
In [42]: def func(i, j):
...: m = i + j
...: return np.where(m % 2 == 0, 1 / (two_at) ** (m / 2), 0)
...:
...: matrix = np.fromfunction(func, (4 + 1, 4 + 1))
In [43]: matrix
Out[43]:
array([[1. , 0. , 0.5 , 0. , 0.25 ],
[0. , 0.5 , 0. , 0.25 , 0. ],
[0.5 , 0. , 0.25 , 0. , 0.125 ],
[0. , 0.25 , 0. , 0.125 , 0. ],
[0.25 , 0. , 0.125 , 0. , 0.0625]])
With this func, fromfunction doesn't buy us much; just pass broadcastable 1d arrays instead:
In [44]: func(np.arange(5)[:,None], np.arange(5))
Out[44]:
array([[1. , 0. , 0.5 , 0. , 0.25 ],
[0. , 0.5 , 0. , 0.25 , 0. ],
[0.5 , 0. , 0.25 , 0. , 0.125 ],
[0. , 0.25 , 0. , 0.125 , 0. ],
[0.25 , 0. , 0.125 , 0. , 0.0625]])
In my other answer I used multiplication to apply the cond to the results.
As for the comparison with loops. Timings with a small example often favor list and iterative solutions. numpy fares much better when sizes are in the 1000s.
Some timings:
In [55]: timeit matrix = np.fromfunction(func, (4 + 1, 4 + 1))
47.2 µs ± 94.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [56]: timeit func(np.arange(5)[:,None], np.arange(5))
33.7 µs ± 112 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [61]: %%timeit
...: res = np.zeros((5,5))
...: for i in range(5):
...: for j in range(5):
...: m=i+j
...: if m%2==0:
...: res[i,j] = 1/(two_at)** (m/2)
...:
...:
9.77 µs ± 26.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
But increase the size:
In [62]: %%timeit
...: res = np.zeros((500,500))
...: for i in range(500):
...: for j in range(500):
...: m=i+j
...: if m%2==0:
...: res[i,j] = 1/(two_at)** (m/2)
...:
...:
71.9 ms ± 206 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [63]: timeit func(np.arange(500)[:,None], np.arange(500))
33.3 ms ± 65.3 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
deffunction - lambdas are limited to a single expression, which makes it hard to read anything non-trivial.two_atto the function? I get how to usefromfunctionif passing only indices. I will read the docs, it must be in there. numpy docs have never let me down before. I thinkprogramcreekhas some examples. Looks like it isn't an issue so long as I make the function inside the function that defines two_at.fromfunctiongenerates all indices and passes then as arrays to your function. Your function expects scalari,j, not 2d arrays.fromfunctionis the wrong function for this.