How do I shorten this code to remove one piece of information from each submatrix?

1 次查看(过去 30 天)
I currently have a Matrix (Mcell) made up of 27390 submatrices which are either 2 by 2. or 1 by 1.
For example:
Mcell{1,1} = 8 -0.5
24 -0.6
I need to extract the value 8 (In the 1,1 position) from each of the sub-matrices and have it in a list it doesn't matter if it's a column or a row.
So far I can do this using this code:
A=[Mcell{1,1}(1,1) Mcell{2,1}(1,1) Mcell{3,1}(1,1) Mcell{4,1}(1,1) Mcell{5,1}(1,1)];
But that only works for the first 5, and I need to replicate it for all of them.
I have tried doing the following:
for i= 1:27390;
A=[Mcell{i,1}(1,1)];
end
But it just gave me the 1,1 value for Mcell{27390,1}. Rather than a list of values.
I also need to do this for the {2,1} position of each submatrix but I'm hopeful I can use the same code for both.
It would also need to preserve the length (27390), so where there wasn't a submatrix value for the (2,1) position a '0' needs to go in it's place.
Many thanks
  2 个评论
James Tursa
James Tursa 2016-5-26
编辑:James Tursa 2016-5-26
What does "extract 8" mean? Do you simply mean "extract the (1,1) or (2,1) element of each cell"? For your example above, what would be the desired output?
Olivia Lynes
Olivia Lynes 2016-5-26
The desired output would be 8, from the (1,1) element. I've edited the question so hopefully it makes sense.

请先登录,再进行评论。

采纳的回答

Guillaume
Guillaume 2016-5-26
Since all your 2D matrices are the same size you might as well all store them as pages of a 3D matrix. This would make your problem easy to solve with simple indexing:
Mmatrix = cat(3, Mcell{:}); %concatenate all matrices along the 3rd dimension
%get element (1, 1) of all matrix:
A = squeeze(Mmatrix(1, 1, :))
The reason your for loop does not work is because you don't do any concatenation in the loop. You just keep on overwriting A all the time. This would work
A = [];
for idx = 1:numel(Mcell) %don't hardcode matrix size when you can simply ask matlab what it is
A = [A, Mcell{idx}(1, 1)];
end
but would be extremely slow due to the constant resizing. This would be slightly faster:
A = zeros(1, numel(Mcell));
for idx = 1 : numel(Mcell)
A(idx) = Mcell{idx}(1, 1);
end
But my first solution is the fastest and most flexible.
  6 个评论
Guillaume
Guillaume 2016-5-27
The error occurs because of a mix-up between linear and subscript indexing (which is a bit my fault, sorry).
The if tests that the index is less than the number of elements regardless of the shape of the matrix (I use numel). That in no way guarantee that there are two rows.
So:
A = zeros(1, numel(Mcell)); %preinitialise A full of zeros
rowtoretrieve = 2;
coltoretrieve = 1;
for idx = 1 : numel(Mcell)
if rotoretrieve < = size(mCell{idx}, 1) && coltoretrieve <= size(mCell{idx}, 2)
A(idx) = Mcell{idx}(rowtoretrieve, coltoretrieve);
end
end

请先登录,再进行评论。

更多回答(2 个)

James Tursa
James Tursa 2016-5-26
编辑:James Tursa 2016-5-26
E.g., to extract the (1,1) element of each cell:
A = cellfun(@(x)x(1,1),Mcell);
For the (2,1) element,
A = cellfun(@(x)x(2,1),Mcell);
etc.
  1 个评论
Olivia Lynes
Olivia Lynes 2016-5-26
Thank you, these both work great.
I've just discovered that not all my submatrices have (2,1) elements is there a way to add in a "If there isn't a (2,1) found insert a 0". so I can maintain the length.
Many thanks and sorry for the follow up.

请先登录,再进行评论。


Jos (10584)
Jos (10584) 2016-5-27
编辑:Jos (10584) 2016-5-27
Using an anonymous helper function creating an inline conditional, this is doable with cellfun:
% inline conditional
iif = @(varargin) varargin{2 * find([varargin{1:2:end}], 1, 'first')}();
% data
MyCell = {[1 2 ; 3 4],[],[10 12],[100 ; 200]}
R = 2 ; C = 1 ;
% get value at (R,C) from each matrix in the cell array.
% If this is not possible, return a NaN
fun = @(M) iif ((R <= size(M,1) && C <= size(M,2)), @() M(R,C), 1, NaN)
X = cellfun(fun , MyCell)
% → X = [3 NaN NaN 100]
  3 个评论
Jos (10584)
Jos (10584) 2016-5-27
I fully agree this is obscure! Yet, it does show that branching is possible using function handles. I love matlab for making this kind of code possible :)
Your second statement is not true, as the last two inputs to iif are "true,NaN".
Guillaume
Guillaume 2016-5-27
I would love matlab more if they'd not restricted anonymous functions to not having branching or assignment which would eliminate the need for these workarounds. I understand where that comes from in a pass-by-value world, but still it's woefully underpowered compared to other languages. And since matlab also has to some pass-by-reference (handle classes) blocking assignment does not always make sense.
What I meant is that the syntax of the iif is iif(condition1, action1, condition2, action2, ...). If none of the conditions are true then the function errors. You indeed avoided that problem by forcing the last condition to always be true. However, it's a bit unnexpected to have a to define a elseif true do ... in a branching statement, so it could be easily forgotten.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Matrix Indexing 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by