How to use cell arrays in Matlab? - arrays

I am a beginner at using Matlab and came across cell arrays but I am not sure how to use indexing for it.
I have created a cell array of 5 rows and 3 cols by doing the following:
A = cell(5,3);
Now is it possible to go through the cell array by row first and then col like how a nested for loop for a normal array?
for i=1:5
for j=1:3
A{i,j} = {"random"} //random numbers/ string etc
end
end

With cell arrays you have two methods of indexing namely parenthesis (i.e. (...)) and braces (i.e. {...}).
Lets create a cell array to use for examples:
A = {3, 9, 'a';
'B', [2,4], 0};
Indexing using paranthesis returns a portion of the cell array AS A CELL ARRAY. For example
A(:,3)
returns a 2-by-1 cell array
ans =
'a'
0
Indexing using braces return the CONTENTS of that cell, for example
A{1,3}
returns a single character
ans =
a
You can use parenthesis to return a single cell as well but it will still be a cell. You can also use braces to return multiple cells but these return as comma separated lists, which is a bit more advanced.
When assigning to a cell, very similar concepts apply. If you're assigning using parenthesis, then you must assign a cell matrix of the appropriate size:
A(:,1) = {1,1}
if you assign a single value using parenthesis, then you must put it in a cell (i.e. A(1) = 2 will give you an error, so you must do A(1) = {2}). So it's better to use braces as then you are directly affecting the contents of the cell. So it is correct to go
A{1} = 2
this is equivalent to A(1) = {2}. Note that A{1} = {2}, which is what you've done, will not give a error but what is does is nests a cell within your cell which is unlikely what you were after.
Lastly, if you have an matrix inside one of your cells, then Matlab allows you to index directly into that matrix like so:
A{2,2}(1)
ans =
3

for example:
for i=1:5
for j=1:3
A{i,j} = rand(3)
end
end
should work perfectly fine
just skip the { } on the right side of the =

Related

Targeting specific elements of cell arrays (Matlab)

I currently have a cell array consisting of 7x1 vectors. I need to extract the first element (1,1) of each vector from each cell and store these values in a new array. This is what I currently have:
for j = 1:numel(xvalues)
cellj = xvalues{j};
a = cellj(1:1);
avalues(1:j) = a;
end
However, I am just generating a cell array with the first element of the last cell, repeating.
How can I fix this?
You can also use cellfun to apply a function to each element in a cell array. So to extract the first element of each vector the following should work.
avalues = cellfun(#(x) x(1),xvalues);
Cellfun loops through each element in the cell array and passes it in to the anonymous function via #(x). We then process x by taking the first element x(1).
In cases such as yours, where the cell contents are matrices of the same size, and assuming your inputs are small enough (meaning that neither memory nor runtime are imminent issues) you can convert the cell array into a numeric matrix and select a vector along the relevant dimension:
function out = q48740494
%% Generate some data:
c = squeeze(num2cell(randi(20,7,1,20),[1,2]));
% c = 20×1 cell array of {7x1 double}
%% Convert this into a numeric array and output:
out = cell2mat(c.'); out = out(1,:);
% BONUS: another version of the line above.
% out = subsref(cell2mat(c.'), substruct('()', {1,1:numel(c)}) ) ;

Applying Movmedian Within Cell Array

I have a cell array (2 x 6) called "output", each cell in row #1 {1 -> 6, 2} contains a 1024 x 1024 x 100 matrix. I want to apply movmedian to each cell in row #1. I would like to apply this function in dimension = 3 with window size = 5.
output = cellfun(#movmedian(5,3), output,'uniform', 0);
This is the code that I have come up with so far, however, it produces an "unbalenced or unexpected parenthesis or bracket" error. I am unsure what is causing this error. I am also somewhat unsure how to instruct matlab to perform this operation only on row 1 of the cell array, please help!
Thank you for your time!!
The function handle passed as the first argument to cellfun will be sequentially passed the contents of each cell (i.e. each 3-D matrix). Since you need to also pass the additional parameters needed by movmedian, you should create an anonymous function like so:
#(m) movmedian(m, 5, 3)
Where the input argument m is the 3-D matrix. If you want to apply this to the first row of output, you just have to index the cell array like so:
output(1, :)
This will return a cell array containing the first row of output, with : indicating "all columns". You can use the same index in the assignment if you'd like to store the modified matrices back in the same cells of output.
Putting it all together, here's the solution:
output(1, :) = cellfun(#(m) movmedian(m, 5, 3), output(1, :),...
'UniformOutput', false);
...and a little trick to avoid having to specify 'UniformOutput', false is to encapsulate the results of the anonymous function in a cell array:
output(1, :) = cellfun(#(m) {movmedian(m, 5, 3)}, output(1, :));

Matlab loop to assign rows to cell array

I have a big cell array A=cell(a,b,c,d) and a row vector B with dimensions 1-by-b.
I want to build a loop in MATLAB that does the following:
for i=1:n
B = Calculate_row(input1,input2) %this is a function that creates my B row
A{a,:,c,i} = B(:)
end
anyway if I try to do A{a,:,c} = B(:) I receive the following error:
Expected one output from a curly brace or dot indexing expression, but there were b results.
And if I try to do A(a,:,c) = B(:) I receive the following error:
Conversion to cell from double is not possible.
Is there a way to do this? (I know a less elegant way that probably works would be to assign each value to the cell separately, but I would prefer not to do it).
One way to do this is to make B a cell array and then take advantage of comma-separated-lists:
B_cell = num2cell(B);
[A{a,:,c}] = B_cell{:} %// or [A{a,:,c,i}] = B_cell{:} if tim's comment is correct
Have a look at Loren Shure's article Deal or No Deal and also this answer for more.
The problem with your syntax, A{a,:,c} = B(:), is that the RHS (i.e. B(:)) is just one single matrix whereas the LHS is a comma-separated-list of b results. So you are basically requesting that 1 output be assigned to b variables and MATLAB doesn't like that, also hence the error message.
The problem with A(a,:,c) = B(:) is that indexing a cell array with () returns a cell array and you can't just assign a matrix (i.e. B(:)) to a cell array hence you second error.

How can I check whether an element is in a nested cell array?

How can I check whether an element is in a nested cell array?
ex:
A = {{4 5 6};{6 7 8}};
b = 5;
The function
ismember(b,A{1})
does not work.
Is there any solution better than for-loop?
Because each element is a cell, you don't have a choice but to use cellfun combined with ismember, which is the same as using a loop in any case. Your cells are specifically two-deep (per Andrew Janke). Each cell element in your cell array is another cell array of individual elements, so there is no vectorized solution that can help you out of this.
Assuming that each cell is just a 1-D cell array of individual elements, you would thus do:
A = {{4 5 6};{6 7 8}};
b = 5;
out = cellfun(#(x) ismember(b, cell2mat(x)), A);
Which gives us:
out =
1
0
This checks to see if the value b is in each of the nested cell arrays. If it is your intention to simply check for its existence over the entire nested cell array, use any on the output, and so:
out = any(cellfun(#(x) ismember(b, cell2mat(x)), A));
Because each cell element is a cell array of individual elements, I converted these to a numerical vector by cell2mat before invoking ismember.

which structure I should use for this matlab arrays

I'm starting to develop a project which uses multi-dimensional arrays very often.
my arrays are mostly 2 , 3 dimensional or so.
As a 2D array sample consider 'A', I may have 2 or more 1D arrays in a cell.
sth like
A=[1, [78,9] [10,65], 9;
2 , 3 , 6;
7 , [9,1] , [91,41,96][10,-1]]
As you saw in 'A(1,2)' there are two 1D arrays.
I don't know which structure I should use to achieve such thing.
moreover I want to be able to have access to all those 1D arrays.
please share your knowledge with me.
try using cell or struct i would recommend cell.
E.g. preinitialize A1:
A1=cell(3,3)
(that would be a 3x3 cell array/matrix). Then you can adress elements with curly brackets ({}). E.g.:
A1{1,1}= 1;
A1(1,1)={1};
both work. You can also define many cells in one line. E.g:
A1(2,:) = {2,3,6};
For the cases with multiarray entries use another cell structure:
B= {[78,9], [10,65]};
A1(1,2) = {B};
and so on. Pay attention to use curly brackets around B (or the coordinate in A1)! Otherwise he would try to merge the cells from B in A1 but that won't do any good because B is a 1x2 cell and you want to give it as argument to one cell in A1.
If you want to return the value inside a cell you have to use curly brackets again:
A1{1,1}
would return 1.
It depends on what you want to do with such a structure. You could use cell arrays for each 1d array entry, and create a matrix of such cell arrays:
a = {1, 2};
b = {-1, 4, 6};
M = [a b];
Alternatively, you can define a sparse 3d array.

Resources