Using Python daily for more than three years as part of my scientific workflow and then abruptly returning to regular Matlab use has made me realise how much better Matlab could be and how evident its idiosyncrasies are. Conversely, while I was aware and noticed that Python makes things simple, it is Matlab’s comparative flaws that really made me come to appreciate just how much has been achieved in the past decade by the community in making Python an indispensable scientific tool.
An aim of this post is to recognize Python’s impressive convenience and versatility. Unfortunately, however, this post more naturally develops by taking the pessimistic approach of highlighting Matlab’s flaws. What follows are several minor, and a few major, annoyances that I’ve noticed on returning to Matlab.
Arithmetic on arrays should not require .*
or ./
Half of Matlab’s name comes from “Matrix”, but I’d bet the majority of its users, like me, seldom use matrices and instead simply work with arrays. Consequently, the vast majority of the time, multiplication and division should act elementwise. In these cases, rather than simply write x*y
or x/y
we are required to write x.*y
or x./y
This syntax obviously cannot be changed, but at least for me, the periods are both unsightly and, when forgotten, cause otherwise unnecessary errors.
Matlab is lacking +=
, -=
, *=
, and /=
operators
The simplest way to describe the +=
operator is to note that the following two lines are equivalent:
x = x + a
x += a
Nothing terribly fancy, but once you get used to using these operators in Python, their absence in Matlab is annoying.
Does anyone actually want lines on their pcolor or filled contour plots?
If Matlab had better defaults, I wouldn’t have to always type shading flat
after a call to pcolor
or 'LineColor', 'none'
in a call to countourf
. I seldom want these outlines on my plots. If I do, I should have to ask for them.
Suppressing the output of every line shouldn’t require a semicolon
Printing a variable or the output of a command within an m-file should require an explicit call to disp
. Too often a forgotten semicolon will cause a giant array to be printed to the command window. (Here’s a reasonable work-around)
hold on
should not be a thing
Three plot commands, say three line plots, one after another should produce three lines on a plot. Matlab, however, will show only the third line unless explicitly instructed to hold the other lines on the plot. Such instruction should not be required for such a common task.
A special function shouldn’t be required for multiple definitions
In Python a, b, c = 1, 2, 3
quickly defines three variables. In Matlab, I have to call the particular function deal
to achieve this otherwise simple task:
[a, b, c] = deal(1, 2, 3);
Matters only get worse when trying to define variables from an array. For example, let X
be a 3 × 10 array. In Python, I could assign each row to a variable as simply as a, b, c = X
The same thing in Matlab is far more verbose: [a, b, c] = deal(X(1, :), X(2, :), X(3, :))
Plotting requires too many calls to squeeze
Routine commands such as mean
or max
effectively reduce the dimension of an array by 1, e.g., a 3D array becomes a 2D array. Before plotting the resulting array using pcolor
or contour
, however, I must squeeze
it to remove the singleton dimension just introduced. Surely it shouldn’t be too difficult for Matlab to recognize that an array of size, say, (20, 1, 15) can be safely treated as 2D.
Python, by comparison, removes singleton dimensions automatically unless explicitly told not to.
Specifying figure size is cumbersome
Creating a figure of a specific size is a common task that Matlab makes overly difficult. It’s possible, but not intuitive. In Python, the simple keyword argument figsize
in a call to figure
will set the desired size. Matlab requires setting two parameters: PaperPosition
and Position
. These parameters do not even default to the same unit, which necessitates setting a third Units
parameter.
I don’t know where my cursor is
In any panel in any figure, Python tells me the current (x, y) coordinate of my cursor:
Something close to this is possible in Matlab, though you might never know. I know only because I specifically set out to reproduce this surprisingly useful feature I learned from Python.
Getting good help is difficult
Most Matlab-related issues that I google point me to the Matlab Answers forum. Conversely, most Python-related issues point me to StackOverflow. The latter has a far superior user experience and, in my subjective opinion at least, more concise and more helpful answers.
Functions should be easy
Everything so far represents a minor annoyance. My biggest issues with Matlab, however, is an inability to quickly and easily create useful functions wherever and whenever I like.
Useful functions in Matlab require either a separate m-file or nesting within another function. (Anonymous functions can be defined anywhere, but their restriction to a single line often makes them impractical.) Python, however, allows function definitions wherever they are desired. A multi-line function can be defined at the command line within a REPL workflow or several function can be defined within a single Python file. The additional hassle of having to create individual files for each function discourages modular code. Instead, codes that could be modular too easily become fragile, stream-of-conciousness scripts without high-level structure.
Defining Matlab functions becomes even more cumbersome once optional arguments get involved. First consider Python’s approach for a simple function to, say, quickly compare two arrays x and y:
def compare_xy(x, y, plot_timeseries=True, ... print_corr=False, start_index=0)
The actual code doesn’t matter. What matters is how straightforward it is to define several input parameters and their default values by using keyword arguments. Conversely, optional arguments in Matlab require one of two awkward approaches. The first goes something like
function compare_xy(x, y, varargin) if nargin == 3 print_corr = false; start_index = 1; else if nargin == 4 ....
I see this approach a lot. It tends to be quicker when there are a limited number of possible input parameters, but it still requires several lines of simple definitions. Furthermore, the input parameter order is fixed resulting in cases where, say, defining the fourth parameter requires also defining the third parameter even if it is unchanged from the default.
The more sophisticated approach is to use inputParser
:
function compare_xy(x, y, varargin) p = inputParser; addParameter(p, 'plot_timeseries', true); addParameter(p, 'print_corr', false); addParameter(p, 'start_index', 1); parse(p, varargin{:}); plot_timeseries = p.Results.plot_timeseries; print_corr = p.Results.print_corr; start_index = p.Results.start_index ...
This isn’t difficult, it’s just so verbose by comparison with Python.
And more
See Part 2
One thought on “Python spoilt me; returning to Matlab is hard”
Comments are closed.