Parameters to numpy's fromfunction
Solution 1:
The documentation is very misleading in that respect. It's just as you note: instead of performing f(0,0), f(0,1), f(1,0), f(1,1)
, numpy performs
f([[0., 0.], [0., 1.]], [[1., 0.], [1., 1.]])
Using ndarrays rather than the promised integer coordinates is quite frustrating when you try and use something likelambda i: l[i]
, where l
is another array or list (though really, there are probably better ways to do this in numpy).
The numpy vectorize
function fixes this. Where you have
m = fromfunction(f, shape)
Try using
g = vectorize(f)
m = fromfunction(g, shape)
Solution 2:
I obviously didn't made myself clear. I am getting responses that fromfunc
actually works as my test code demonstrates, which I already knew because my test code demonstrated it.
The answer I was looking for seems to be in two parts:
The fromfunc
documentation is misleading. It works to populate the entire array at once.
Note: Since writing this question, the documentation has been updated to be clearer.
In particular, this line in the documentation was incorrect (or at the very minimum, misleading)
For example, if
shape
were (2, 2), then the parameters in turn be (0, 0), (0, 1), (1, 0), (1, 1).
No. If shape
(i.e. from context, the second parameter to the fromfunction
) were (2,2), the parameters would be (not 'in turn', but in the only call):
(array([[ 0., 0.], [ 1., 1.]]), array([[ 0., 1.], [ 0., 1.]]))
The documentation has been updated, and currently reads more accurately:
The function is called with N parameters, where N is the rank of shape. Each parameter represents the coordinates of the array varying along a specific axis. For example, if shape were (2, 2), then the parameters would be array([[0, 0], [1, 1]]) and array([[0, 1], [0, 1]])
(My simple example, derived from the examples in the manual, may have been misleading, because +
can operate on arrays as well as indices. This ambiguity is another reason why the documentation is unclear. I want to ultimately use a function that isn't array based, but is cell-based - e.g. each value might be fetched from a URL or database based on the indices, or even input from the user.)
Returning to the problem - which is how can I populate an array from a function that is called once per element, the answer appears to be:
You cannot do this in a functional style.
You can do it in an imperative/iterative style - i.e. writing nested for-loops, and managing the index lengths yourself.
You could also do it as an iterator, but the iterator still needs to track its own indices.