Retrieving element index in spfun, cellfun, arrayfun, etc. in MATLAB
Is there any way to retrieve the index of the element on which a function called by cellfun
, arrayfun
or spfun
acts? (i.e. retrieve the index of the element within the scope of the function).
For the sake of simplicity, imagine I have the following toy example开发者_开发问答:
S = spdiags([1:4]',0,4,4)
f = spfun(@(x) 2*x,S)
which builds a 4x4 sparse diagonal matrix and then multiplies each element by 2
.
And say that now, instead of multiplying each element by the constant number 2
, I would like to multiply it by the index the element has in the original matrix, i.e. assuming that linear_index
holds the index for each element, it would be something like this:
S = spdiags([1:4]',0,4,4)
f = spfun(@(x) linear_index*x,S)
However, note the code above does not work (linear_index
is undeclared).
This question is partially motivated by the fact that blocproc
gives you access to block_struct.location
, which one could argue references the location (~index) of the current element within the full object (an image in this case):
block_struct.location:
A two-element vector, [row col], that specifies the position of the first pixel (minimum-row, minimum-column) of the block data in the input image.
No, but you can supply the linear index as extra argument.
Both cellfun
and arrayfun
accept multiple input arrays. Thus, with e.g. arrayfun, you can write
a = [1 1 2 2];
lin_idx = 1:4;
out = arrayfun(@(x,y)x*y,a,lin_idx);
This doesn't work with spfun
, unfortunately, since it only accepts a single input (the sparse array).
You can possibly use arrayfun
instead, like so:
S = spdiags([1:4]',0,4,4);
lin_idx = find(S);
out = spones(S);
out(lin_idx) = arrayfun(@(x,y)x*y,full(S(lin_idx)),lin_idx);
%# or
out(lin_idx) = S(lin_idx) .* lin_idx;
Note that the call to full
won't get you into memory trouble, since S(lin_idx)
is 0% sparse.
You can create a sparse matrix with linear_index filling instead of values.
Create A
:
A(find(S))=find(S)
Then use A
and S
without spfun, e.g.: A.*S
. This runs very fast.
It's simple. Just make a cell like: C = num2cell(1:length(S)); then: out=arrayfun(@(x,c) c*x,S,C)
精彩评论