Effacer les filtres
Effacer les filtres

Unexpected singleton dimension removal

12 vues (au cours des 30 derniers jours)
Thomas
Thomas le 8 Juil 2014
Commenté : Matt J le 11 Nov 2014
When I create a three dimensional array and assign it to an undefined array, the assignment does not behave as I expect if the first two dimensions are singletons:
>> it = rand(1,1,3)
it(:,:,1) =
0.9157
it(:,:,2) =
0.7922
it(:,:,3) =
0.9595
>> vom(1,:,:) = it
vom =
0.9157 0.7922 0.9595
>> vom(:,1,:) = it
vom =
0.2769
0.0462
0.0971
I know there are a million ways around this, but this behavior seems unnatural to me. Is this singleton dimension removal documented anywhere?
  5 commentaires
Sara
Sara le 8 Juil 2014
But what are you trying to achieve? If you want to assign it to vom, you don't need any indexing. vom1(1,1,1:3) = it will do not remove any dimension.
Thomas
Thomas le 8 Juil 2014
As I said there are plenty of ways around this, in my case size(it,2) is not fixed, and I was doing the assigment
vom(m,:,:) = it;
in a loop. Alternatives are
1) initialize vom by
vom = zeros(0, size(it,2),3)
2) do the assignment as
vom(m, 1:size(it,2), :) = it
3) Initialize vom as empty and assign via concatenation
vom = [vom;it]
Doubtless there are other ways to do this.

Connectez-vous pour commenter.

Réponse acceptée

Matt J
Matt J le 11 Nov 2014
Modifié(e) : Matt J le 11 Nov 2014
Is this singleton dimension removal documented anywhere?
I think the best documentation you'll find will be this excerpt from the SUBSASGN documentation, note the portion in bold
"For multidimensional arrays, a(I,J,K,...) = b assigns b to the specified elements of a. b must be length(I)-by-length(J)-by-length(K)-... or be shiftable to that size by adding or removing singleton dimensions. "
So, in other words, it is applying shiftdim() to the right hand side "b", until it reaches a shape that will work. The question is, when vom is undefined, how does it choose the direction to shift? What accounts for differences in the 3 tests below? I believe the answer is, it will start with a right-shift of 1 and continue to right shift until it finds a shape that will work.
>> clear vom; vom(1,:,:) = it
vom =
0.9134 0.6324 0.0975
>> clear vom; vom(1,:,:) = it(:)
vom =
0.9134 0.6324 0.0975
>> clear vom; vom(1,:,:) = it(:)'
vom(:,:,1) =
0.9134
vom(:,:,2) =
0.6324
vom(:,:,3) =
0.0975
So, in the first test above, "it" is right shiftdimmed by 1 making it into a column vector, but a column vector is not a shape compatible with the indexing vom(1,:,:). The target shape has to be either a row vector or 1x1x3. So, "it" is right shifted again, making it a row vector, which works.
Similarly, in the second test, the right hand side starts as a column vector, gets right shifted by 1, making it a row vector which is a legal target shape, and so that's the shape that gets chosen
Finally, the 3rd test is the most interesting. The given right hand side it(:)' starts as a row vector, and the sensible thing would be to stop there, since this is a legal target shape. However, as I mentioned, the rule is that the code will always attempt at least one right shift and so it converts the right hand side to 1x1x3. But this is also a legal target shape and so that's the shape that gets selected.

Plus de réponses (1)

John D'Errico
John D'Errico le 8 Juil 2014
Clearly, "vom" stands for Volatile Organic Matter, and "it" always means Information Technology. But put them together and you get ... something that makes MATLAB upset.
Seriously, I was a bit surprised myself at first. Apparently MATLAB sees a vector as a vector, as just a vector and no more.
A = rand(1,3);
clear B
B(1,:) = A
B =
0.98946 0.86134 0.70694
clear B
B(:,1) = A
B =
0.98946
0.86134
0.70694
An array is a different thing though.
A = rand(2,2);
clear B
B(1,:) = A
Subscripted assignment dimension mismatch.
I'd prefer there was consistency, but I'll bet this is a legacy thing, harking back to the days of MATLAV Version 1.
  1 commentaire
Matt J
Matt J le 11 Nov 2014
An array is a different thing though.
Not as different as you might think:
>> A=rand(2,2)
A =
0.8003 0.4218
0.1419 0.9157
>> clear B; B(1,:,:)=A
B(:,:,1) =
0.8003 0.1419
B(:,:,2) =
0.4218 0.9157

Connectez-vous pour commenter.

Catégories

En savoir plus sur Logical dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by