iterate over single array dimension
31 ビュー (過去 30 日間)
古いコメントを表示
I am having trouble iterating over a single array dimension. For instance, let's say I have a dozen sets of data, and for each dataset I want to solve the quadratic equation. The polynomial coefficient list for all datasets is stored in a single 2D array with dimensions [12,3].
data = randn(12,3);
For a single set of 3 coefficients, I can use the roots function to get the two roots to the equation. How can I iterate over all 12 datasets? Do I need to write a 'for' loop?
In the past, I used the bsxfun something like the following:
quadraticRoots = bsxfun(@(x,y)roots(x), data, data);
In the days before implicit expansion, this would give me an output array with dimensions [12,2] which is what I want. There are two roots for each of the 12 datasets. With the updates to bsxfun, I get a message that the input must be a vector. Instead of single-dimension expansion, bsxfun implicitly expands everything! Arrayfun is no help because it also implicitly expands each element in the 2D array.
The above case is relatively simple, but I do this type of operation very frequently. I have a list of vectors stored as a 2D array, and want to apply a function to each row or column in the list. Is there a general way to iterate over a single array dimension without a 'for' loop?
2 件のコメント
Guillaume
2019 年 9 月 24 日
As far as I know the behaviour of bsxfun has not changed at all since implicit expansion was introduced. Your usage of bsxfun doesn't make much sense, you've got an anonymous function with two inputs, x and y, but it doesn't use y. And since you're passing twice the same input, there's obviously no expansion to be done. So your equation reduces to (regardless of version):
quadraticRoots = roots(data);
which obviously doesn't work with matrices.
採用された回答
Jon
2019 年 9 月 23 日
You can do it with arrayfun for example
coef = randn(12,3)
qroots = cell2mat(arrayfun(@(n) roots(coef(n,:)),1:size(coef,1),'UniformOutput',false))
This returns a 2 by 12 array of roots, one column for each row of coef. You could of course transpose it if you wanted.
This seems quite arcane though. I don't know if there is any performance advantage of doing it this way rather than just putting it in a loop. Certainly a little loop would be more readable. Maybe someone know how to do this in a cleaner way.
4 件のコメント
Jon
2019 年 9 月 24 日
編集済み: Jon
2019 年 9 月 24 日
I'm not sure about performance, but for readability you could always make yourself a little function like this (would need a little more of a header to fit standard documentation)
function B = rowiter(fun,A)
% iterate input fun over rows of A
% fun is a function handle to a function that accepts a single vector
% input and returns a vector output
% get dimensions
numRows = size(A,1);
% determine length of vector returned by fun
% (assume it is the same for all rows and just check the first)
numCols = numel(fun(A(1,:)));
% preallocate output array
B = zeros(numRows,numCols);
% iterate through rows of A
for k = 1:numRows
out = fun(A(k,:));
B(k,:) = out(:); % use (:) to make sure it is a column
end
and then for the specific example you had you could just apply it for example
coef = randn(12,3);
qroots = rowiter(@roots,coef)
その他の回答 (0 件)
参考
カテゴリ
Help Center および File Exchange で Matrices and Arrays についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!