New in R2020b: new way to return height or width of arrays

Adam Danz 2020년 10월 6일 (2021년 4월 29일에 수정됨)
최근 활동 Rik답글: 2021년 4월 30일

Prior to r2020b the height (number of rows) and width (number of columns) of an array or table can be determined by the size function,

array = rand(102, 16);
% Method 1
[dimensions] = size(array);
h = dimensions(1);
w = dimensions(2);
% Method 2
[h, w] = size(array); %#ok<*ASGLU>
% or
[h, ~] = size(array);
[~, w] = size(array);
% Method 3
h = size(array,1);
w = size(array,2);

In r2013b, the height(T) and width(T) functions were introduced to return the size of single dimensions for tables and timetables.

Starting in r2020b, height() and width() can be applied to arrays as an alternative to the size() function.

Continuing from the section above,

h = height(array)
% h =  102
w = width(array)
% w =  16

height() and width() can also be applied to multidimensional arrays including cell and structure arrays

mdarray = rand(4,3,20);
h = height(mdarray)
% h =  4
w = width(mdarray)
% w =  3

The expanded support of the height() and width() functions means,

  1. when reading code, you can no longer assume the variable T in height(T) or width(T) refers to a table or timetable
  2. greater flexibility in expressions such as the these, below
% C is a 1x4 cell array containing 4 matrices with different dimensions
rng('default')
C = {rand(5,2), rand(2,3), rand(3,4), rand(1,1)};
celldisp(C)
% C{1} =
%       0.81472      0.09754
%       0.90579       0.2785
%       0.12699      0.54688
%       0.91338      0.95751
%       0.63236      0.96489
% C{2} =
%       0.15761      0.95717      0.80028
%       0.97059      0.48538      0.14189
% C{3} =
%       0.42176      0.95949      0.84913      0.75774
%       0.91574      0.65574      0.93399      0.74313
%       0.79221     0.035712      0.67874      0.39223
% C{4} =
%       0.65548

What's the max number of rows in C?

maxRows1 = max(cellfun(@height,C))         % using height()
% maxRows1 =  5;
maxRows2 = max(cellfun(@(x)size(x,1),C))   % using size()
% maxRows2 =  5; 

What's the total number of columns in C?

totCols1 = sum(cellfun(@width,C))          % using width()
%totCols1 =  10
totCols2 = sum(cellfun(@(x)size(x,2),C))   % using size(x,2)
% totCols2 =  10

Attached is a live script containing the content of this post.

Jan
Jan 2021년 1월 29일 (2021년 1월 30일에 수정됨)

A faster version of:

totCols2 = sum(cellfun(@(x)size(x,2),C))

is

totCols2 = sum(cellfun('size', C, 2))

Although 'size' appears in the section "Backward Compatibility" in the documentation, this direct commands are much faster than calling function handles: 'isempty', 'islogical', 'isreal', 'length', 'ndims', 'prodofsize', 'size', 'isclass'

Adam Danz
Adam Danz 2021년 1월 29일

Thanks Jan. Since the string syntax fails with some classes, I avoid using it in demos where users could try to use the same syntax with a class that causes problems. But the benefits in speed of the string syntax is definitely worth it when you know you're dealing with a class that is supported by it.

Rik posted a comment recently that summarizes this well.

For example,

>> C = {rand(2,2), string([])}
C =
  1×2 cell array
    {2×2 double}    {0×0 string}
>> totCols2 = sum(cellfun('size', C, 2))
totCols2 =
     3   % incorrect
>> totCols2 = sum(cellfun(@(x)size(x,2),C))
totCols2 =
     2   % correct
Asad (Mehrzad) Khoddam
Asad (Mehrzad) Khoddam 2020년 10월 7일

Is any equivalent for more than 2D matrices?

Adam Danz
Adam Danz 2020년 10월 7일 (2020년 10월 7일에 수정됨)

Just the good old size(array, n) where n specifies the dimension.

Asad (Mehrzad) Khoddam
Asad (Mehrzad) Khoddam 2020년 10월 7일

Yes, I prefer this method

Rik
Rik 2020년 10월 6일

Maybe people will finally stop teaching length. Previously my lecturing included only numel and size as alternative, but now I have two functions to provide as readable alternatives.

Stephen23
Stephen23 2020년 12월 25일

"Maybe people will finally stop teaching length."

That will be a day to celebrate!

I am yet to find a use-case for length, and much prefer numel and size for their predictability and clarity.

Mario Malic
Mario Malic 2020년 10월 15일

What's the issue with length?

Asking for a friend

Jan
Jan 2021년 4월 30일

I started programming in MATLAB for some analyses in the clinical motion analyses. The trajectories of the measurements have been stored a [nVariables x nTimePoints] matrices. In a subfunction I've determined the number of time points dynamically using LENGTH(), which failed after some years, when I've introduced more variables: Then the number of variables exceeded the width of the array and took some time to find the problem. An equivalent problem occurred at computing the standard deviation between persons: std([nPersons x nVariables x nTimePoints]). A specific group of patients contained one person only and STD() was applied to the 1st non-singelton dimension, which was the 2nd one. The save approach is to specify the dimension to operate on in every case: std(X, 1, 1).

Matlab's "smart" way to guess, which dimension is meant, is a source of bugs. This concerns LENGTH as well as preferring the 1st non-singelton dimension. In short hacks, this saves some seconds for typing, but in productive code for scientific applications it is a good programming practice to specify the dimensions in every case.

Rik
Rik 2021년 4월 30일

I wholeheartedly support your last paragraph. It is similar to my advice for GUI-design: always use specific handles for graphics calls, so the user can click on another figure while your GUI is running, without any major issues.

Rik
Rik 2020년 10월 15일

The issue with length is the unpredictable outcome. You can tell if it will use the height, width, or later dimension. The most common use case will be in a loop:

for n=1:length(A)
    SomeFunction(A(n))
end

In almost every case you want to loop over the rows or the columns or all elements of a matrix. In most cases you know in advance which you need. If you're lucky length will be equivalent to size(A,1) or size(A,2) or numel(A), but if A is not the exact shape you expected, the result will be different.

If you don't tell Matlab what you mean, it will do what ask.