# Speedy variable switching

In oceanographic research we often want to produce plots of various variables either against each other or against depth, time or location.

The main structure of these figures will be very similar regardless of exactly which variable(s) you want to look at, but a whole bunch of settings (axis limits, labels, ticks…) might be different in each case.

Here, we’ll look at a way to set up a figure in MATLAB such that you can very efficiently switch backwards and forwards between the different variables that you might want to visualise, all within a single script. You can use these techniques all the way from initial data exploration up to making full publication-quality figures.

The code in the examples is all available in a .m file on GitHub.

## Have your data in a structure or table

The first thing you need is to have your data to plot in a structure or table. Take a look at my previous blog post for more information on these MATLAB variable types.

Having our data in this format allows us to “dynamically reference” which field we want to use. Let’s take a simple example. Say we have a dataset of salinity and nitrate values, measured across a river estuary. We can simulate a dataset to play with as follows:

``````%% Simulate dataset to play with
clear ts
ts.dist = (0:50:1000)'; % distance along the estuary
ts.sal = 1 + ts.dist * 34/1000 + 0.1*randn(size(ts.dist)); % salinity
ts.no3 = 10 * exp(-ts.dist/3e2) + 0.05*randn(size(ts.dist)); % nitrate
ts = struct2table(ts);
``````

## Make a basic figure

We can visualise the data as follows, starting as always with a `figure(X); clf`:

``````%% Super basic plotting
figure(1); clf
scatter(ts.dist,ts.sal) % data points
``````

To change which variable we want to plot, we could just switch between using `ts.sal` and `ts.no3` as the input to `scatter`.

## Now make it a bit more complex

Now let’s make the figure a bit more complicated; we’ll add a mixing line, and a second subplot that shows deviations from the mixing line.

``````%% Now add a mixing line and second subplot

% Calculate gradient and intercept of mixing line
mixLineGradient = diff(ts.sal([1 end])) / diff(ts.dist([1 end]));
mixLineIntercept = ts.sal(1);

% Create mixing line function of distance
mixLineFunction = @(dist) mixLineIntercept + mixLineGradient * dist;

% Draw figure
figure(1); clf

subplot(2,1,1); hold on
scatter(ts.dist,ts.sal) % data points
plot(ts.dist([1 end]),ts.sal([1 end])) % mixing line

subplot(2,1,2)
scatter(ts.dist,ts.sal - mixLineFunction(ts.dist)) % residuals
`````` Now we have a more complex plot with lots of repetition of `ts.sal` in the code.

Now, if we want to switch to plotting nitrate instead of salinity, we have to change `ts.sal` to `ts.no3` in five different places! Ain’t nobody got time for that, so this is where the aforementioned dynamic referencing comes in.

## Make it dynamic

We define a variable (say `fyvar`) that is just a string containing the name of the variable we want to plot on the y-axes. We then replace `ts.sal` with `ts.(fyvar)` each time it appears:

``````%% As above, but with dynamic y-axis variable

% Decide which variable to plot
fyvar = 'sal';

% Calculate gradient and intercept of mixing line
mixLineGradient = diff(ts.(fyvar)([1 end])) / diff(ts.dist([1 end]));
mixLineIntercept = ts.(fyvar)(1);

% Create mixing line function of distance
mixLineFunction = @(dist) mixLineIntercept + mixLineGradient * dist;

% Draw figure
figure(1); clf

subplot(2,1,1); hold on
scatter(ts.dist,ts.(fyvar)) % data points
plot(ts.dist([1 end]),ts.(fyvar)([1 end])) % mixing line

subplot(2,1,2)
scatter(ts.dist,ts.(fyvar) - mixLineFunction(ts.dist)) % residuals
``````

Now all we have to do to switch between plotting salinity and nitrate is change the value of `fyvar` from `'sal'` to `'no3'`, and everything else sorts itself out automatically. The figure doesn’t look any different from in the previous example.

## Use a switch block for other settings

We may have other settings that we want to be different for the different variables. The best way to implement this is to put a `switch` block towards the start of your code (but after the value for `fyvar` is set).

In this case we would write the following:

``````%% Add axis labels, and a switch block to set their values

% Decide which variable to plot
fyvar = 'no3';

% Variable-specific settings
switch fyvar
case 'sal'
fylabel = 'Salinity';
case 'no3'
fylabel = 'Nitrate';
end %switch

% Calculate gradient and intercept of mixing line
mixLineGradient = diff(ts.(fyvar)([1 end])) / diff(ts.dist([1 end]));
mixLineIntercept = ts.(fyvar)(1);

% Create mixing line function of distance
mixLineFunction = @(dist) mixLineIntercept + mixLineGradient * dist;

% Draw figure
figure(1); clf

subplot(2,1,1); hold on
scatter(ts.dist,ts.(fyvar)) % data points
plot(ts.dist([1 end]),ts.(fyvar)([1 end])) % mixing line
xlabel('Distance')
ylabel(fylabel)

subplot(2,1,2)
scatter(ts.dist,ts.(fyvar) - mixLineFunction(ts.dist)) % residuals
xlabel('Distance')
ylabel([fylabel ' residuals'])
``````

This code executes as follows (noting that we’ve switched to looking at nitrate, not salinity):

1. The value of `fyvar` is set as `'no3'`;
2. The `switch` block tests the value of `fyvar`, finds that it is `'no3'`, so sets `fylabel` to `'Nitrate'`;
3. When we reach `ylabel(fylabel)`, the correct y-axis label of `"Nitrate"` is applied.

## Tell me more about `switch` blocks

A `switch` block is essentially a shorthand way of writing a sequence of `if ... elseif ...` statements, where the thing being tested by the `if` is the same every time. So the block in the example above:

``````switch fyvar
case 'sal'
fylabel = 'Salinity';
case 'no3'
fylabel = 'Nitrate';
end %switch
``````

could alternatively, but less elegantly, be written as:

``````if strcmp(fyvar, 'sal')
fylabel = 'Salinity';
elseif strcmp(fyvar, 'no3')
fylabel = 'Nitrate';
end %if
``````

You can add as many lines of code as you like after each `case` statement, and a single `case` statement can match multiple values if you group them using curly brackets: `{}`.

## I want to see both variables at once!

As a final flourish, once we’ve set up all the coding infrastructure above, we can now very easily draw the plots for both salinity and nitrate side by side, with all of the settings that we’ve defined, by using a `for` loop.

``````%% Use a loop to plot nitrate and salinity side by side

% Define list of variables to plot
fyvars = {'sal' 'no3'};

% Draw figure
figure(1); clf

% Loop through the variables in fyvars
for V = 1:numel(fyvars)

% Pick which variable to plot from fyvars
fyvar = fyvars{V};

% Variable-specific settings
switch fyvar
case 'sal'
fylabel = 'Salinity';
case 'no3'
fylabel = 'Nitrate';
end %switch

% Calculate gradient and intercept of mixing line
mixLineGradient = diff(ts.(fyvar)([1 end])) / diff(ts.dist([1 end]));
mixLineIntercept = ts.(fyvar)(1);

% Create mixing line function of distance
mixLineFunction = @(dist) mixLineIntercept + mixLineGradient * dist;

subplot(2,2,(V-1)*2+1); hold on
scatter(ts.dist,ts.(fyvar)) % data points
plot(ts.dist([1 end]),ts.(fyvar)([1 end])) % mixing line
xlabel('Distance')
ylabel(fylabel)

subplot(2,2,2*V)
scatter(ts.dist,ts.(fyvar) - mixLineFunction(ts.dist)) % residuals
xlabel('Distance')
ylabel([fylabel ' residuals'])

end %for V
`````` An automated side-by-side plot can now be generated with little effort.

The changes that we’ve made to the previous version are:

1. Added a cell of strings containing all the variables we want to plot (`fyvars`);
2. Added a `for` loop that cycles through this cell of strings;
3. Changed the subplots to a 2 by 2 grid, and used a bit of mental arithmetic to figure out the correct subplot number from the value of `V` (the loop counter).

## A note on workflow

In a previous post I discussed figure creation workflow when you are setting something up with publication quality (in the final section before the summary).

In that context, all of the code I’ve described above (and probably still a fair bit more) would come in the first section of the workflow, when you’re still setting up the figure and watching it in MATLAB, and before you add in the `print` statement to output the results to a file.

## Summary

• Prepare your data in a table or structure and you can very easily change the variables that are plotted on complex figures;
• Use a `switch` block to control variable-specific settings;
• Put the whole lot in a `for` loop to display multiple variables at once.