Look at the error:
In [171]: np.fromfunction(f, ds.shape)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-171-1a3ed1ade41a> in <module>
----> 1 np.fromfunction(f, ds.shape)
/usr/local/lib/python3.6/dist-packages/numpy/core/numeric.py in fromfunction(function, shape, **kwargs)
2026 dtype = kwargs.pop('dtype', float)
2027 args = indices(shape, dtype=dtype)
-> 2028 return function(*args, **kwargs)
2029
2030
TypeError: <lambda>() takes 1 positional argument but 2 were given
fromfunction is a small Python function; there's no compiled magic.
Based on the shape you give, it generates indices.
In [172]: np.indices(ds.shape)
Out[172]:
array([[[0, 0, 0],
[1, 1, 1],
[2, 2, 2]],
[[0, 1, 2],
[0, 1, 2],
[0, 1, 2]]])
That's a (2,3,3) array. The 2 from the 2 element shape, and the (3,3) from the shape itself. This is similar to what np.meshgrid and np.mgrid produce. Just indexing arrays.
It then passes that array to your function, with *args unpacking.
function(*args, **kwargs)
In [174]: f(Out[172][0], Out[172][1])
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-174-40469f1ab449> in <module>
----> 1 f(Out[172][0], Out[172][1])
TypeError: <lambda>() takes 1 positional argument but 2 were given
That's all it does - generate a n-d grid, and pass it as n arguments to your function.
===
Note also that you passed ds.shape to fromfunction, but not ds itself. You could just as well written np.fromfunction(f,(3,3)).
What do you want your lambda to do with ds? Clearly fromfunction isn't doing it for you.
===
With this f, the only that fromfunction can do is give it a arange:
In [176]: np.fromfunction(f, (10,))
Out[176]: 45.0
In [177]: f(np.arange(10))
Out[177]: 45.0
===
In the linked SO the lambda takes 2 arguments, lambda x,y:
np.fromfunction(lambda x,y: np.abs(target[0]-x) + np.abs(target[1]-y), ds.shape)
In that SO, both the question and answer, the ds array is just the source of the shape, Target is (0,1), the largest element of ds.
Effectively, the fromfunction in the linked answer is just doing:
In [180]: f1 = lambda x,y: np.abs(0-x) + np.abs(1-y)
In [181]: f1(Out[172][0], Out[172][1])
Out[181]:
array([[1, 0, 1],
[2, 1, 2],
[3, 2, 3]])
In [182]: np.abs(0-Out[172][0]) + np.abs(1-Out[172][1])
Out[182]:
array([[1, 0, 1],
[2, 1, 2],
[3, 2, 3]])
In [183]: np.abs(np.array([0,1])[:,None,None]-Out[172]).sum(axis=0)
Out[183]:
array([[1, 0, 1],
[2, 1, 2],
[3, 2, 3]])
In [184]: np.abs(0-np.arange(3))[:,None] + np.abs(1-np.arange(3))
Out[184]:
array([[1, 0, 1],
[2, 1, 2],
[3, 2, 3]])