Concatenate cell array in MATLAB - arrays

In Matlab you can concatenate arrays by saying:
a=[];
a=[a,1];
How do you do something similar with a cell array?
a={};
a={a,'asd'};
The code above keeps on nesting cells within cells. I just want to append elements to the cell array. How do I accomplish this?

If a and b are cell arrays, then you concatenate them in the same way you concatenate other arrays: using []:
>> a={1,'f'}
a =
1×2 cell array
{[1]} {'f'}
>> b={'q',5}
b =
1×2 cell array
{'q'} {[5]}
>> [a,b]
ans =
1×4 cell array
{[1]} {'f'} {'q'} {[5]}
You can also use the functional form, cat, in which you can select along which dimension you want to concatenate:
>> cat(3,a,b)
1×2×2 cell array
ans(:,:,1) =
{[1]} {'f'}
ans(:,:,2) =
{'q'} {[5]}
To append a single element, you can do a=[a,{1}], but this is not efficient (see this Q&A). Instead, do a{end+1}=1 or a(end+1)={1}.
Remember that a cell array is just an array, like any other. You use the same tools to manipulate them, including indexing, which you do with (). The () indexing returns the same type of array as the one you index into, so it returns a cell array, even if you index just a single element. Just about every value in MATLAB is an array, including 6, which is a 1x1 double array.
The {} syntax is used to create a cell array, and to extract its content: a{1} is not a cell array, it extracts the contents of the first element of the array.
{5, 8, 3} is the same as [{5}, {8}, {3}]. 5 is a double array, {5} is a cell array containing a double array.
a{5} = 0 is the same as a(5) = {0}.

Related

MATLAB: Convert cell array of 1D strings to 2D string

Recent versions of MATLAB have strings, which are N-Dimensional matrices of character vectors. I have a cell array of such 1D strings that I would like to combine into a single 2D string, but I am having a lot of trouble doing so. The join, strjoin and strcat functions work on the characters arrays inside the string, and cell2mat doesn't work:
>> cell2mat({strings(1, 4); strings(1, 4)})
Error using cell2mat (line 52)
CELL2MAT does not support cell arrays containing cell arrays or objects.
Is there any good way to do this? I expect the output in the above case to be a 2x1 string object.
string objects behave just like any other datatype (double, char, etc.) when it comes to concatenation with the same type. As long as you want the result to also be a string object, use normal concatenation.
result = [strings(1, 4); strings(1, 4)];
Or you can use cat or vertcat to be more explicit
result = cat(1, strings(1, 4), strings(1, 4));
result = vertcat(strings(1, 4), strings(1, 4));
Alternately you could use indexing to sample the same element twice
result = strings([1 1], 4);
If your data is already in a cell array, then you can use {:} indexing to generate a comma-separated list that you can pass to cat
C = {string('one'), string('two')};
result = cat(1, C{:})
As a side-note, there is no such thing as a 1-dimensional array in MATLAB. All arrays are at least two dimensions (one of which can be 1).

How do I convert a cell array w/ different data formats to a matrix in Matlab?

So my main objective is to take a matrix of form
matrix = [a, 1; b, 2; c, 3]
and a list of identifiers in matrix[:,1]
list = [a; c]
and generate a new matrix
new_matrix = [a, 1;c, 3]
My problem is I need to import the data that would be used in 'matrix' from a tab-delimited text file. To get this data into Matlab I use the code:
matrix_open = fopen(fn_matrix, 'r');
matrix = textscan(matrix_open, '%c %d', 'Delimiter', '\t');
which outputs a cell array of two 3x1 arrays. I want to get this into one 3x2 matrix where the first column is a character, and the second column an integer (these data formats will be different in my implementation).
So far I've tried the code:
matrix_1 = cell2mat(matrix(1,1));
matrix_2 = cell2mat(matrix(1,2));
matrix = horzcat(matrix_1, matrix_2)
but this is returning a 3x2 matrix where the second column is empty.
If I just use
cell2mat(matrix)
it says it can't do it because of the different data formats.
Thanks!
This is the help of matlab for the cell2mat function:
cell2mat Convert the contents of a cell array into a single matrix.
M = cell2mat(C) converts a multidimensional cell array with contents of
the same data type into a single matrix. The contents of C must be able
to concatenate into a hyperrectangle. Moreover, for each pair of
neighboring cells, the dimensions of the cell's contents must match,
excluding the dimension in which the cells are neighbors. This constraint
must hold true for neighboring cells along all of the cell array's
dimensions.
From what I understand the contents you want to put in a matrix should be of the same type otherwise why do you want a matrix? you could simply create a new cell array.
It's not possible to have a normal matrix with characters and numbers. That's why cell2mat won't work here. But you can store different datatypes in a cell-array. Use cellstr for the strings/characters and num2cell for the integers to convert the contents of matrix. If you have other datatypes, use an appropriate function for this step. Then assign them to the columns of an empty cell-array.
Here is the code:
fn_matrix = 'data.txt';
matrix_open = fopen(fn_matrix, 'r');
matrix = textscan(matrix_open, '%c %d', 'Delimiter', '\t');
X = cell(size(matrix{1},1),2);
X(:,1) = cellstr(matrix{1});
X(:,2) = num2cell(matrix{2});
The result:
X =
'a' [1]
'b' [2]
'c' [3]
Now we can do the second part of the question. Extracting the entries where the letter matches with one of the list. Therefore you can use ismember and logical indexing like this:
list = ['a'; 'c'];
sel = ismember(X(:,1),list);
Y(:,1) = X(sel,1);
Y(:,2) = X(sel,2);
The result here:
Y =
'a' [1]
'c' [3]

Convert a vector to string in matlab and search for this string inside a cell array

Suppose I have a vector created after concatenating horizontally 3 variables:
>>a=1;
>>b=0;
>>c=1;
>>vector=horzcat(a,b,c);
Now what i want to do is converting this vector to string and put this vector in a cell table.
>>string=mat2str(vector);
>>string =
[1 0 1]
>> C = cell(2, 2);
>> C{1}{1}=string
>> C =
{1x1 cell} []
[] []
My problem is: how to search for this value in a cell array? i tried the following:
find(strcmp(C, string))
ans =
Empty matrix: 0-by-1
as you can see, matlab can't find this vector converted to string inside the cell array. Is there any easier way to do this?
Are you sure you want this:
C{1}{1}=string
and not this:
C{1,1}=string
?
If you use the second method, then find(strcmp... will work. The first method won't work because you are making a cell matrix within a cell matrix and then asking strcmp to compare your string directly with a cell...

What is the difference between the data stored in a cell and the data stored as double in MATLAB?

I have two variables who look exactly the same to me, but one is <double> and the other is <cell>. In the code it seems that they are converted by cell2mat. I understand it is a question of data storage but I just don't see the difference and the definition of cell and double for this.
Adding to nrz's answer, it is noteworthy that there is an additional memory overhead when storing cell arrays. For instance, consider the following code:
A = 1:5
B = {A}
C = num2cell(A)
whos
which produces the following output:
A =
1 2 3 4 5
B =
[1x5 double]
C =
[1] [2] [3] [4] [5]
Name Size Bytes Class Attributes
A 1x5 40 double
B 1x1 152 cell
C 1x5 600 cell
As you can see from the first line, the basic 1-by-5 vector A of doubles takes 40 bytes in memory (each double takes 8 bytes).
The second line shows that just wrapping A with a single cell to produce B adds extra 112 bytes. That's the overhead of a single cell in MATLAB.
The third line confirms that, because C contains 5 cells and takes (112+8)×5 = 600 bytes.
Arrays and cell arrays are probably the two most commonly used data types in MATLAB.
1D and 2D arrays are matrices just like in mathematics, in linear algebra. But arrays can also be multidimensional (n-dimensional) arrays, also called tensors, MATLAB calls them multidimensional arrays. Further, MATLAB does not make any distinction between scalars and arrays, nor between vectors and other matrices. A scalar is just a 1x1 array in MATLAB, and vectors are Nx1 and 1xN arrays in MATLAB.
Some examples:
MyScalar = 1;
MyHorizVector = [ 1 2 3 ];
MyVertVector = [ 1 2 3 ]';
MyMatrix = [ 1, 2; 3, 4 ];
My4Darray = cat(4, [ 1 2; 3 4], [ 5 6; 7 8 ], [ 9 10; 11 12 ], [ 13 14; 15 16 ]);
class(MyScalar)
ans =
double
class(MyHorizVector)
ans =
double
class(MyVertVector)
ans =
double
class(MyMatrix)
ans =
double
class(My4Darray)
ans =
double
So, the class of all these 5 different arrays is double, as reported by class command. double means the numeric precision used (double-precision).
The cell array is a more abstract concept. A cell array can hold one or more arrays, it can also hold other types of variables that are not arrays. A cell array can also hold other cell arrays which can again hold whatever a cell array can hold. So, cell arrays can also be stored recursively inside one another.
Cell arrays are useful for combining different objects into a single variable that can eg. be passed to a function or handled with cellfun. Each cell array consists of 1 or more cells. Any array can be converted to cell array using { } operators, the result is a 1x1 cell array. There are also mat2cell and num2cell commands available.
MyCellArrayContainingMyScalar = { MyScalar };
MyCellArrayContainingMyHorizVector = { MyHorizVector };
MyCellArrayContainingMyCellArrayContainingMyScalar = { MyCellArrayContainingMyScalar };
All cell arrays created above are 1x1 cell arrays.
class(MyCellArrayContainingMyScalar)
ans =
cell
class(MyCellArrayContainingMyHorizVector)
ans =
cell
class(MyCellArrayContainingMyCellArrayContainingMyScalar)
ans =
cell
But not all cell arrays can be converted into matrices using cell2mat, because a single cell array can hold several different data types that cannot exist in the same array.
These do work:
cell2mat(MyCellArrayContainingMyScalar)
ans =
1
cell2mat(MyCellArrayContainingMyHorizVector)
ans =
1 2 3
But this fails:
cell2mat(MyCellArrayContainingMyCellArrayContainingMyScalar);
Error using cell2mat (line 53)
Cannot support cell arrays containing cell arrays or objects.
But let's try a different kind of a cell array consisting of different arrays:
MyCellArray{1} = [ 1 2 3 ];
MyCellArray{2} = 'This is the 2nd cell of MyCellArray!';
class(MyCellArray)
ans =
cell
This cell array neither cannot be converted to an array by using cell2mat:
cell2mat(MyCellArray)
Error using cell2mat (line 46)
All contents of the input cell array must be of the same data type.
Hope this helps to get an idea.

How do concatenation and indexing differ for cells and arrays in MATLAB?

I am a little confused about the usage of cells and arrays in MATLAB and would like some clarification on a few points. Here are my observations:
An array can dynamically adjust its own memory to allow for a dynamic number of elements, while cells seem to not act in the same way:
a=[]; a=[a 1]; b={}; b={b 1};
Several elements can be retrieved from cells, but it doesn't seem like they can be from arrays:
a={'1' '2'}; figure; plot(...); hold on; plot(...); legend(a{1:2});
b=['1' '2']; figure; plot(...); hold on; plot(...); legend(b(1:2));
%# b(1:2) is an array, not its elements, so it is wrong with legend.
Are these correct? What are some other different usages between cells and array?
Cell arrays can be a little tricky since you can use the [], (), and {} syntaxes in various ways for creating, concatenating, and indexing them, although they each do different things. Addressing your two points:
To grow a cell array, you can use one of the following syntaxes:
b = [b {1}]; % Make a cell with 1 in it, and append it to the existing
% cell array b using []
b = {b{:} 1}; % Get the contents of the cell array as a comma-separated
% list, then regroup them into a cell array along with a
% new value 1
b{end+1} = 1; % Append a new cell to the end of b using {}
b(end+1) = {1}; % Append a new cell to the end of b using ()
When you index a cell array with (), it returns a subset of cells in a cell array. When you index a cell array with {}, it returns a comma-separated list of the cell contents. For example:
b = {1 2 3 4 5}; % A 1-by-5 cell array
c = b(2:4); % A 1-by-3 cell array, equivalent to {2 3 4}
d = [b{2:4}]; % A 1-by-3 numeric array, equivalent to [2 3 4]
For d, the {} syntax extracts the contents of cells 2, 3, and 4 as a comma-separated list, then uses [] to collect these values into a numeric array. Therefore, b{2:4} is equivalent to writing b{2}, b{3}, b{4}, or 2, 3, 4.
With respect to your call to legend, the syntax legend(a{1:2}) is equivalent to legend(a{1}, a{2}), or legend('1', '2'). Thus two arguments (two separate characters) are passed to legend. The syntax legend(b(1:2)) passes a single argument, which is a 1-by-2 string '12'.
Every cell array is an array! From this answer:
[] is an array-related operator. An array can be of any type - array of numbers, char array (string), struct array or cell array. All elements in an array must be of the same type!
Example: [1,2,3,4]
{} is a type. Imagine you want to put items of different type into an array - a number and a string. This is possible with a trick - first put each item into a container {} and then make an array with these containers - cell array.
Example: [{1},{'Hallo'}] with shorthand notation {1, 'Hallo'}

Resources