3d matrix inline initialization - matlab

Is there any way to inline initialize a 3D matrix in MATLAB in a single line? Thus, without use of for-loops and pre-initialization, e.g. via zero(a,b,c). As far as I know we can only do 2D as in:
matr=[1,2;3,4]
where , and ; indicate the two dimensions. Is there any deliminator for the third dimension that I do not know about? I know that the a multi-line initilization is possible via
matr(:,:,1) = [1 2 3; 9 8 7; 4 6 5];
matr(:,:,2) = [0 3 2; 8 8 4; 5 3 5];
matr(:,:,3) = [6 4 7; 6 8 5; 5 4 3];

Use cat to concatenate along the third dimension:
cat(3, [1 2 3; 9 8 7; 4 6 5], [0 3 2; 8 8 4; 5 3 5], [6 4 7; 6 8 5; 5 4 3])
You can also achieve this using reshape:
reshape([[1 2 3; 9 8 7; 4 6 5], [0 3 2; 8 8 4; 5 3 5], [6 4 7; 6 8 5; 5 4 3]], [3,3,3])

Related

Find which matrix row has values specified from array

How can I find which row in a matrix has a specified set values that I entered in an array?
So for example;
A = [4 5 6 7;
8 4 5 6;
4 5 6 8;
8 4 8 9;
1 2 2 4;
5 3 4 6];
and I want to find which row has the vector of [4 5 6 8]
You can use a combination of all and find...
With implicit expansion (R2016b or newer)
find( all( A == [4 5 6 8], 2 ) )
Equivalently you can use bsxfun (compatible with all MATLAB versions)
find( all( bsxfun( #eq, A, [4 5 6 8] ), 2 ) )
The output in both cases is 3 from your example A.
I would go for #Wolfie's approach, assuming order matters.
Another possibility is to use ismember. This can be used both when order matters and when it doesn't. Let
A = [4 5 6 7; 8 4 5 6; 4 5 6 8; 8 4 8 9; 1 2 2 4; 5 3 4 6];
v = [4 5 6 8];
If order matters:
result = find(ismember(A, v, 'rows'));
If order doesn't matter:
result = find(all(ismember(A, v), 2));

How to combine matrix of different size in a cell array into a matrix in MATLAB

Similarly to How to combine vectors of different length in a cell array into matrix in MATLAB I would like to combine matrix having different dimension, stored in a cell array, into a matrix having zeros instead of the empty spaces. Specifically, I have a cell array {1,3} having 3 matrix of size (3,3) (4,3) (4,3):
A={[1 2 3; 4 5 6; 7 8 9] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]}
and I would like to obtain something like:
B =
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
0 0 0 9 9 9 4 4 4
I tried using cellfun and cell2mat but I do not figure out how to do this. Thanks.
Even if other answers are good, I'd like to submit mine, using cellfun.
l = max(cellfun(#(x) length(x),A))
B = cell2mat(cellfun(#(x) [x;zeros(l-length(x),3)], A, 'UniformOutput', 0));
Using bsxfun's masking capability -
%// Convert A to 1D array
A1d = cellfun(#(x) x(:).',A,'Uni',0) %//'
%// Get dimensions of A cells
nrows = cellfun('size', A, 1)
ncols = cellfun('size', A, 2)
%// Create a mask of valid positions in output numeric array, where each of
%// those numeric values from A would be put
max_nrows = max(nrows)
mask = bsxfun(#le,[1:max_nrows]',repelem(nrows,ncols)) %//'
%// Setup output array and put A values into its masked positions
B = zeros(max_nrows,sum(ncols))
B(mask) = [A1d{:}]
Sample run
Input -
A={[1 2 3 5 6; 7 8 9 3 8] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]}
Output -
B =
1 2 3 5 6 1 2 3 1 2 3
7 8 9 3 8 4 5 6 4 5 6
0 0 0 0 0 7 8 9 7 8 9
0 0 0 0 0 9 9 9 4 4 4
I would be surprised if this is possible in one or a few lines. You will probably have to do some looping yourself. The following achieves what you want in the specific case of incompatible first dimension lengths:
A={[1 2 3; 4 5 6; 7 8 9] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]}
maxsize = max(cellfun(#(x) size(x, 1), A));
B = A;
for k = 1:numel(B)
if size(B{k}, 1) < maxsize
tmp = B{k};
B{k} = zeros(maxsize, size(tmp,1));
B{k}(1:size(tmp,1),1:size(tmp,2)) = tmp;
end
end
B = cat(2, B{:});
Now B is:
B =
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
0 0 0 9 9 9 4 4 4
I would do it using a good-old for loop, which is quite intuitive I think.
Here is the commented code:
clc;clear var
A={[1 2 3; 4 5 6; 7 8 9] [1 2 3; 4 5 6; 7 8 9; 9 9 9] [1 2 3; 4 5 6; 7 8 9; 4 4 4]};
%// Find the maximum rows and column # to initialize the output array.
MaxRow = max(cell2mat(cellfun(#(x) size(x,1),A,'Uni',0)));
SumCol = sum(cell2mat(cellfun(#(x) size(x,2),A,'Uni',0)));
B = zeros(MaxRow,SumCol);
%// Create a counter to keep track of the current columns to fill
ColumnCounter = 1;
for k = 1:numel(A)
%// Get the # of rows and columns for each cell from A
NumRows = size(A{k},1);
NumCols = size(A{k},2);
%// Fill the array
B(1:NumRows,ColumnCounter:ColumnCounter+NumCols-1) = A{k};
%// Update the counter
ColumnCounter = ColumnCounter+NumCols;
end
disp(B)
Output:
B =
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
0 0 0 9 9 9 4 4 4
[max_row , max_col] = max( size(A{1}) , size(A{2}) , size(A{3}) );
A{1}(end:max_row , end:max_col)=0;
A{2}(end:max_row , end:max_col)=0;
A{3}(end:max_row , end:max_col)=0;
B=[A{1} A{2} A{3}];
for this specific problem, simply this will do:
B=cat(1,A{:});
or what I often just give a try for 2D cells, and works for your example as well:
B=cell2mat(A');
if you literally don't give a f* what dimension it will be cut in (and you're exceedingly lazy): put the same into a try-catch-block and loop over some dims as below.
function A=cat_any(A)
for dims=1:10% who needs more than 10 dims? ... otherwise replace 10 with: max(cellfun(#ndims,in),[],'all')
try, A=cat(dims,A{:}); end
if ~iscell(A), return A; end
end
disp('Couldn''t cat!') %if we can't cat, tell the user
end
Beware, this might lead to unexpected results ... but in most cases simply just worked for me.

How to enter 3D matrix in Matlab?

How to enter 3D matrix in Matlab?
Is the only way is with cat function, like this:
cat(3, [1 2 3; 9 8 7; 4 6 5], [0 3 2; 8 8 4; 5 3 5], ...
[6 4 7; 6 8 5; 5 4 3])
may be it is possible to with brackets and semicolons?
you can use assignment to slices:
A(:,:,1) = [1 2 3; 9 8 7; 4 6 5];
A(:,:,2) = [0 3 2; 8 8 4; 5 3 5];
A(:,:,3) = [6 4 7; 6 8 5; 5 4 3];

How do I add mirrored padding around a matrix?

I have a matrix and want to add padding around it but the padded values have to be mirrored.
I have tried using A = padarray(B,[1 1],'symmetric','both');
but it mirrors the edge values of matrix B.
Meaning if
B = [1 2 3;
4 5 6;
7 8 9];
the result will be
A = [1 1 2 3 3;
1 1 2 3 3;
4 4 5 6 6;
7 7 8 9 9;
7 7 8 9 9]
But I need A to look like this:
A = [5 4 5 6 5;
2 1 2 3 2;
5 4 5 6 5;
8 7 8 9 8;
5 4 5 6 5]
Is there some function like padarray I can use for that or do I have to do it manually?
You could use symmetric with [2 2] and remove the extra parts,
B = [1 2 3; 4 5 6; 7 8 9];
c = padarray(B,[2 2],'both','symmetric');
c(end-1,:) = [];
c(:,end-1) = [];
c(:,2) = [];
c(2,:) = [];
gives,
c =
5 4 5 6 5
2 1 2 3 2
5 4 5 6 5
8 7 8 9 8
5 4 5 6 5

Markertype of scatter points in Matlab based on condition

Suppose I have the following data:
xData = [4 7 2 1 2 8 7 1 1 3];
yData = [1 2 3 4 5 6 7 8 9 10];
P = [5 10 4 2 7 3 8 1 9 3];
I want to use a different markertype based on P. If the corresponding element in P<5 then 'o' and if P>5 then '^'. I know how to do this based on colour (although I don't actually know how to specify what colours to use?) but can this be done with markertype?
scatter(xData,yData,70,P>5)
Any ideas? Thanks!
You will need to do 2 scatter plots with less and more:
xData = [4 7 2 1 2 8 7 1 1 3];
yData = [1 2 3 4 5 6 7 8 9 10];
P = [5 10 4 2 7 3 8 1 9 3];
x_less = xData(P < 5);
x_more = xData(P >= 5);
y_less = yData(P < 5);
y_more = yData(P >= 5);
figure;
scatter(x_less, y_less, 20, 'r', 'o')
hold on
scatter(x_more, y_more, 20, 'b', '^')
This will give you an example like this:
Hope this helps.