How to enter 3D matrix in Matlab? - 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];

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));

3d matrix inline initialization

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])

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 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.