Is cell2mat supposed to support non-plaid cell partitioning? If not, why not?

1 visualizzazione (ultimi 30 giorni)
I have 2 cell arrays,
load C; C,Ct
C = 2×2 cell array
{2×1 double} {[ 2 3 4]} {[ 1]} {2×3 double}
Ct = 2×2 cell array
{[ 5 9]} {[ 1]} {3×1 double} {3×2 double}
Why does cell2mat work on one,
cell2mat(C)
ans = 3×4
5 2 3 4 9 6 7 8 1 10 11 12
but not the other?
cell2mat(Ct)
Error using cat
Dimensions of arrays being concatenated are not consistent.

Error in cell2mat (line 83)
m{n} = cat(1,c{:,n});
I understand that the cell partitioning of Ct is not plaid, but nor is it for C.
  3 Commenti
Rik
Rik il 30 Mar 2022
I would not have expected any non-plaid partitions to work, but that first example is straight from the documentation and works as far back as ML6.5 (from 20 years ago).
The documention does state this: "For example, the contents of cells in the same column must have the same number of columns, although they need not have the same number of rows". However, it is unclear why this limitation does not apply to the rows of the cell array.
Either the documentation is not clear enough that the rows are less restricted than the columns, or this is not intended.
Since the documentation doesn't suggest this limitation, I would personally consider this a bug.

Accedi per commentare.

Risposta accettata

Bruno Luong
Bruno Luong il 30 Mar 2022
But this one works
Ctlarge={rand(1,2) rand(1,1) rand(1,0); rand(3,1) rand(3,2) rand(3,0)}
Ctlarge = 2×3 cell array
{[0.4947 0.3734]} {[ 0.1931]} {1×0 double} {3×1 double } {3×2 double} {3×0 double}
cell2mat(Ctlarge)
ans = 4×3
0.4947 0.3734 0.1931 0.0224 0.9756 0.3280 0.1889 0.3083 0.7573 0.5897 0.9973 0.1664
You can edit the function to see why !
  2 Commenti
Matt J
Matt J il 30 Mar 2022
Modificato: Matt J il 30 Mar 2022
Cool! Is it because it consolidates cells along the longest dimension of the array first?
Bruno Luong
Bruno Luong il 30 Mar 2022
Modificato: Bruno Luong il 30 Mar 2022
Yes, longest in term of cell length not final array length. In case of draw, working on columns first.

Accedi per commentare.

Più risposte (1)

Rik
Rik il 30 Mar 2022
This doesn't answer your actual question, but below is code that should work on all combinations of non-plaid partitions. Some of the code is already ND, while other parts are limited to 1/2D. It isn't perfect, but it works on this example. I didn't spend much time optimizing to limit data copies etc, so the performance will be terrible. You can adapt the first loop to check if you need this function in the first place.
C={[5;9],[2 3 4];
1,[6 7 8;10 11 12]};
%create fully transposed array
Ct=C.';for n=1:numel(Ct),Ct{n}=Ct{n}.';end
cell2mat_slow_nonplaid(C)
ans = 3×4
5 2 3 4 9 6 7 8 1 10 11 12
cell2mat_slow_nonplaid(Ct).' % <-- transpose yet again for a sanity check
ans = 3×4
5 2 3 4 9 6 7 8 1 10 11 12
function out=cell2mat_slow_nonplaid(C)
% replicate the function of cell2mat for non-plaid partitions
%check if the number of elements along a dimension is the same over the cell array (i.e. is the
%total number of columns the same for each column in the cell array)
sz=cell(1,max(cellfun(@ndims,C(:))));
for dim=1:numel(sz)
sz{dim}=cellfun('size',C,dim);
sz{dim}=unique(sum(sz{dim},dim));
if 1 ~= numel(sz{dim})
error('dimension %d doesn''t match',dim)
end
end
sz=horzcat(sz{:});
%determine the number of rows preceeding each element
rows_preceeding=zeros(size(C));
dim=1;
for r=2:size(C,1) % skip the first row
for c=1:size(C,2)
rows_preceeding(r,c)=size(C{r-1,c},dim);
end
end
rows_preceeding=cumsum(rows_preceeding,dim);
%determine the number of columns preceeding each element
cols_preceeding=zeros(size(C));
dim=2;
for r=1:size(C,1)
for c=2:size(C,2) % skip the first col
cols_preceeding(r,c)=size(C{r,c-1},dim);
end
end
cols_preceeding=cumsum(cols_preceeding,dim);
%store the parts in the final array
out=cell(sz);
for n=1:numel(C)
r=rows_preceeding(n)+(1:size(C{n},1));
c=cols_preceeding(n)+(1:size(C{n},2));
tmp=num2cell(C{n});
out(r,c)=tmp;
end
%all elements should contain exactly 1 value now
%we only need to unwind this without affecting the type
out=cell2mat(out);
end
  2 Commenti
Matt J
Matt J il 30 Mar 2022
Modificato: Matt J il 30 Mar 2022
I don't really need a nonplaid cell2mat. I was impressed that you attempted one, however, and was inspired to do likewise. I've designed the implementation below to be fully N-dimensional, but like you I've only done limited testing. I'm not sure it will handle the case where some of the cells are empty.
C(:,:,1)={rand(1,2,2) rand(1,1,1);
rand(3,1,2) rand(3,2,2)};
C(:,:,2)={rand(1,2,1) rand(1,1,2);
rand(3,1,1) rand(3,2,1)};
A=cell2matNonPlaid(C)
A =
A(:,:,1) = 0.8392 0.8342 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN A(:,:,2) = 0.6641 0.6722 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN A(:,:,3) = NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 NaN 0.2872 NaN NaN 0.5795 NaN NaN 0.2795 NaN NaN A(:,:,2) = 0.6641 0.6722 NaN 0.6475 NaN NaN 0.0900 NaN NaN 0.4762 NaN NaN A(:,:,3) = NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 NaN NaN 0.5795 NaN NaN 0.2795 NaN NaN A(:,:,2) = 0.6641 0.6722 NaN 0.6475 NaN NaN 0.0900 NaN NaN 0.4762 NaN NaN A(:,:,3) = NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 0.0431 0.0317 0.5795 0.6404 0.1901 0.2795 0.9640 0.2928 A(:,:,2) = 0.6641 0.6722 NaN 0.6475 0.6358 0.6526 0.0900 0.6653 0.0129 0.4762 0.9024 0.7033 A(:,:,3) = NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 0.0431 0.0317 0.5795 0.6404 0.1901 0.2795 0.9640 0.2928 A(:,:,2) = 0.6641 0.6722 NaN 0.6475 0.6358 0.6526 0.0900 0.6653 0.0129 0.4762 0.9024 0.7033 A(:,:,3) = 0.9011 0.5322 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 0.0431 0.0317 0.5795 0.6404 0.1901 0.2795 0.9640 0.2928 A(:,:,2) = 0.6641 0.6722 NaN 0.6475 0.6358 0.6526 0.0900 0.6653 0.0129 0.4762 0.9024 0.7033 A(:,:,3) = 0.9011 0.5322 NaN 0.2546 NaN NaN 0.9315 NaN NaN 0.5628 NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 0.0431 0.0317 0.5795 0.6404 0.1901 0.2795 0.9640 0.2928 A(:,:,2) = 0.6641 0.6722 0.6683 0.6475 0.6358 0.6526 0.0900 0.6653 0.0129 0.4762 0.9024 0.7033 A(:,:,3) = 0.9011 0.5322 0.2761 0.2546 NaN NaN 0.9315 NaN NaN 0.5628 NaN NaN
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 0.0431 0.0317 0.5795 0.6404 0.1901 0.2795 0.9640 0.2928 A(:,:,2) = 0.6641 0.6722 0.6683 0.6475 0.6358 0.6526 0.0900 0.6653 0.0129 0.4762 0.9024 0.7033 A(:,:,3) = 0.9011 0.5322 0.2761 0.2546 0.8762 0.2373 0.9315 0.9836 0.6985 0.5628 0.2408 0.8808
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
A =
A(:,:,1) = 0.8392 0.8342 0.8830 0.2872 0.0431 0.0317 0.5795 0.6404 0.1901 0.2795 0.9640 0.2928 A(:,:,2) = 0.6641 0.6722 0.6683 0.6475 0.6358 0.6526 0.0900 0.6653 0.0129 0.4762 0.9024 0.7033 A(:,:,3) = 0.9011 0.5322 0.2761 0.2546 0.8762 0.2373 0.9315 0.9836 0.6985 0.5628 0.2408 0.8808
function A=cell2matNonPlaid(C)
nd=ndims(C);
Nd=max(cellfun(@ndims,C(:)));
siz=cellfun(@size,C,'uni',0);
siz=cellfun(@(x) [ x, ones(1,Nd-numel(x)) ], siz,'uni',0 );
subs0=num2cell(ones(1,Nd));
dims=nan(1,Nd);
corners=cell(1,Nd);
for i=1:Nd
subs=subs0; subs{i}=':';
S=siz(subs{:});
c=cell2mat(S(:));
s=sum(c,1);
dims(i)=s(i);
P=cellfun(@(c) c(i),siz);
corners{i}=cumsum(P,i)-(P-1);
end
corners=cat(Nd+1,corners{:});
corners=reshape(corners,[],Nd);
A=nan(dims);
for i=1:numel(C)
lower=corners(i,:);
upper=lower+siz{i}-1;
range=arrayfun(@(a,b) a:b, lower, upper,'uni',0);
A(range{:})=C{i}
disp ' '
disp '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
disp ' '
end
end
Bjorn Gustavsson
Bjorn Gustavsson il 31 Mar 2022
@Rik and @Matt J: Impressive efforts. (But there's no way I would manage to use this type of tiling-functionality without severely shoot my feet clean off - and that's already for 2-D usage.) Impressive efforts!

Accedi per commentare.

Categorie

Scopri di più su Matrices and Arrays in Help Center e File Exchange

Prodotti


Release

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by