Cell Arrays
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Written against MATLAB R2026b. The sessions below were run in GNU Octave 11.3.0 (MATLAB code that Octave also accepts) and show Octave’s output; MATLAB displays cell arrays in a different layout (1×3 cell array with {[42]} entries). Where an error message is quoted from MATLAB it is labelled "not run here" or the wording is described rather than quoted, because messages vary between releases and Octave’s differ.
A cell array is an array whose elements are cells, and each cell can hold a value of any type and size: a number, a matrix, text, a structure, a function handle or another cell array. Ordinary numeric, logical and character arrays require every element to have the same type; a cell array exists to hold data that is not uniform, for example a row of a messy spreadsheet that mixes sensor names, readings and flags. The documentation positions cell arrays as the container for non-tabular data accessed by numeric index, and points tabular data to Tables and text-only data to string arrays (see Strings and Character Arrays). Cells also appear everywhere in the language: as varargin and varargout (Variable Number of Arguments) and as comma-separated lists (Comma-Separated Lists).
Creating cell arrays
Curly braces build a cell array, with commas or spaces between the columns and semicolons between the rows, exactly like square brackets build a numeric array. The function cell preallocates an empty cell array whose cells each contain [].
c = cell(m,n) % m-by-n array of empty cells
c = {'S1', 21.5, [1 2 3]; 'S2', 22.0, {4, 'x'}}
c = {'S1', 21.5, [1 2 3]; 'S2', 22.0, {4, 'x'}};
size(c)
class(c(1,2))
class(c{1,2})
class(c{2,3})
c{2,3}{2}
Octave 11.3.0 output:
ans =
2 3
ans = cell
ans = double
ans = cell
ans = x
The array has two rows and three columns. The cell c(1,2) is a cell; its contents c{1,2} is a double; the element c{2,3} is itself a cell array (a nested cell array), and c{2,3}{2} reaches into it with a second pair of braces.
Parentheses return cells, braces return contents
This is the central distinction of the page, and the cause of most cell-array errors.
| Syntax | Meaning | Result |
|---|---|---|
|
Paren indexing: the cell at row 2, column 1 |
A 1-by-1 cell array |
|
Paren indexing: a sub-array of cells |
A cell array |
|
Brace indexing: the contents of one cell |
The stored value, of its own type |
|
Brace indexing of several cells |
A comma-separated list of contents (see Comma-Separated Lists) |
|
Brace to reach the contents, then ordinary indexing into it |
One element of the matrix stored in that cell |
|
Paren assignment: the right side must be a cell array |
Replaces the cell |
|
Brace assignment: stores a value in the cell |
Replaces the contents |
Parentheses select a part of the container, so the type of the result is still cell. Braces open the container and hand you what is inside. The documentation phrases it as: enclose indices in curly braces to read or write the contents within a cell, and use parentheses to refer to cells (to replace several cells at once, assign a cell array of the same size with parentheses).
sub = c(:,1)
x = c{1,3}(2)
Octave 11.3.0 output:
sub =
{
[1,1] = S1
[2,1] = S2
}
x = 2
sub is a 2-by-1 cell array; x is the second element of the vector [1 2 3] stored in c{1,3}.
Growing and deleting cells
Assigning to an index beyond the current size grows the array and fills the new cells with []; assigning [] with parentheses deletes cells (a whole row or column at a time, as with numeric arrays).
d = cell(2,3);
isempty(d{1,1})
c(1,:) = [];
size(c)
c{end+1,1} = 'S3';
size(c)
Octave 11.3.0 output:
ans = 1
ans =
1 3
ans =
2 3
After deleting the first row, c is 1-by-3; assigning to c{end+1,1} adds a row, so it is 2-by-3 again with empty cells in the new row. Growing inside a loop reallocates repeatedly; preallocate with cell when the size is known (see Vectorization and Preallocation).
Concatenation works with both bracket types: [c1, c2] joins cell arrays into a larger cell array, and {c1, c2} nests them as two cells.
Text in cell arrays: iscellstr and cellstr
A cell array of character vectors was the way to store a list of strings before string arrays arrived in R2016b. iscellstr tests whether every cell holds a character vector, and cellstr converts a character array or string array to that form.
names = {'north','south','east'};
iscellstr(names)
iscellstr(c)
Octave 11.3.0 output: ans = 1, then ans = 0 (the second c contains numbers and a nested cell). Many older functions still accept or return cells of character vectors (strsplit, regexp with 'match', dir-style listings, some file-dialog functions). In new code prefer a string array ["north" "south" "east"], which supports == comparison, contains, join and sorting without cellfun; convert with string(names) when you need to, and with cellstr when an old interface demands a cell array.
Processing contents with cellfun
cellfun applies a function to the contents of every cell, which replaces a loop and the {} indexing inside it.
A = cellfun(func, C) % uniform output, an ordinary array
A = cellfun(func, C, UniformOutput=false) % a cell array of any outputs
[A1,A2] = cellfun(func, C) % several outputs
A = cellfun(func, C1, C2) % several cell arrays, element by element
By default the function must return one scalar (of a type that can be concatenated) for every cell, and the results are collected into an array of the same size. When the function returns vectors, text or anything of varying size, set UniformOutput to false and the results come back as a cell array. The name-value syntax UniformOutput=false is the modern form and the one used below; the older 'UniformOutput', false pair also works. Octave 11.3.0 accepts only the pair, so the output shown was produced with it.
names = {'north','south','east'};
lens = cellfun(@numel, names)
up = cellfun(@upper, names, UniformOutput=false)
[mx, ix] = cellfun(@max, {[1 5 2],[7 3]})
Octave 11.3.0 output (with 'UniformOutput', false in the second call):
lens =
5 5 4
up =
{
[1,1] = NORTH
[1,2] = SOUTH
[1,3] = EAST
}
mx =
5 7
ix =
2 1
lens is a numeric row because numel returns a scalar for each cell. up needs UniformOutput set to false because each result is a character vector of a different length. The third call shows multiple outputs: the maximum and its position in each vector. A second name-value argument, ErrorHandler, names a function that is called instead of stopping when an element fails; it receives an error structure and the inputs. Old code also passes the function as text, as in cellfun('isempty', C); the handle form cellfun(@isempty, C) is the one to write today.
Source: MATLAB documentation: cellfun
Related functions: arrayfun (the same idea over the elements of an ordinary array or a struct array, see Structures) and structfun (over the fields of a struct).
Converting to and from arrays
-
cell2mat©concatenates the contents of a cell array into one ordinary array. The contents must have the same type (all numeric, all character, all logical, or all cells or structures) and must fit together by the usual concatenation rules, row by row and column by column. -
num2cell(A)does the opposite: it puts each element of the arrayAin its own cell. -
mat2cell(A, r, c)splits a matrix into blocks of the given row and column sizes, one block per cell. -
struct2cell,cell2struct,cell2table,table2cellandcellstrconvert between cell arrays and the other containers.
m = cell2mat({[1 2], [3]; [4 5], [6]})
n = num2cell([1 2; 3 4])
Octave 11.3.0 output:
m =
1 2 3
4 5 6
n =
{
[1,1] = 1
[2,1] = 3
[1,2] = 2
[2,2] = 4
}
In cell2mat, each row of cells is joined horizontally ([1 2] next to 3, [4 5] next to 6) and then the rows are stacked, so the blocks of a row must have the same height and the rows the same total width. Mixing types fails: cell2mat({1,'a'}) raises an error (Octave 11.3.0 prints cell2mat: wrong type elements or mixed cells, structs, and matrices; MATLAB raises an error with its own text, not run here).
When to prefer another container
| Your data | Better choice |
|---|---|
A list of names or labels |
A string array: it compares, sorts and searches directly, and is a regular array |
Records with the same named fields, accessed by name |
A structure array (Structures) |
Rows of mixed-type columns, such as a sensor log, to filter, group and summarise |
A table or timetable (Tables, Timetables) |
Lookup by a key (an identifier, a name) |
A |
Genuinely heterogeneous items accessed by position, results of variable length, argument lists |
A cell array |
In the heatflow scenario (The heatflow scenario) a cell array fits a list of sensor records read from a messy file, or the varargin of a function that accepts name-value options, while the cleaned sensors.csv data belongs in a table.
Common errors
-
Brace indexing a non-cell. Applying
{}to a variable that is not a cell array, as inx = 5; x{1}, fails with the identifierMATLAB:cellRefFromNonCell(the message says that brace indexing is not supported for variables of this type; the exact wording varies by release, not run here). Octave 11.3.0 printsscalar cannot be indexed with {instead. It usually means a variable that you expected to be a cell array is a plain array, often because a function returned a different type than before. The fix is to checkiscell(x)or to find where the cell array was lost. -
Index out of bounds.
c = {1,2,3}; c{4}fails with an out-of-bounds index error (the identifier isMATLAB:badsubscriptin MATLAB; Octave 11.3.0 printsc(4): out of bound 3 (dimensions are 1x3)with the identifierOctave:index-out-of-bounds). Reading beyond the end is an error; assigning beyond the end grows the array. -
Assigning a non-cell with parentheses.
c(2) = 7stores a value into a cell with parentheses. MATLAB rejects it with a conversion error (not run here), because the parentheses expect a cell array on the right; writec{2} = 7orc(2) = {7}. Octave 11.3.0 is more permissive and silently wraps the value, so a script that runs in Octave can still fail in MATLAB here. -
Non-uniform output from cellfun.
cellfun(@(v) [v v], {1,2,3})fails because the results are not scalars; addUniformOutputset to false. Octave 11.3.0 printscellfun: all values must be scalars when UniformOutput = true; MATLAB raises an error with a message about the output not being a scalar (not run here). -
Treating a list as one value.
C{:}is a comma-separated list, not a value (see Comma-Separated Lists). -
Display versus content.
{[100]}in the Command Window shows a cell holding a number;[100]without braces is a plain number.
Where older books differ
Books for MATLAB 5 to 7 cover cells as a new container and rely on cellfun with character shortcuts, on cellstr and char to exchange text lists, and on struct-like workarounds. The mechanics of () versus {} have not changed. What is newer: string arrays (R2016b) replace most cells of text, UniformOutput=false as a name-value argument (R2021a for the Name=Value syntax in general), tables (R2013b) replace many mixed-type cell arrays read from files, and readcell (R2019a) reads a spreadsheet or delimited text into a cell array.