Plotting subplots in a figure automatically for each column of matrix - matlab

For example let's say I have a following matrix (<9x6 double>) with a colheaders(<1x6 cell>).
Matrix =
226.7431 14.7437 14.9417 14.1000 14.5000 66.0590
226.7500 14.6582 14.8250 NaN 14.2000 66.7740
226.7569 14.3590 14.6067 NaN 13.9000 68.4897
226.7639 14.2702 14.5717 13.4000 13.8000 68.2487
226.7708 14.2555 14.6000 NaN 14.0000 NaN
226.7778 14.1605 14.5967 NaN 13.9000 NaN
226.7847 14.0320 14.4567 12.9000 13.6000 68.8272
226.7917 13.8422 14.2733 NaN 13.4000 69.6392
226.7986 13.6585 14.1169 NaN 13.1000 69.8048
I want to plot first column of matrix on x-axis and the rest on y-axis in a matlab figure with subplots (let's say 3 in one figure). Manually I can do something like this a figure and so on.
figure
subplot(3,1,1)
plot(Matrix(:,1),Matrix(:,2),'ro'); grid on; box on; xlabel('A');ylabel('B')
subplot(3,1,2)
plot(Matrix(:,1),Matrix(:,3),'bo'); grid on; box on; xlabel('A');ylabel('C')
subplot(3,1,3)
plot(Matrix(:,1),Matrix(:,4),'go'); grid on; box on; xlabel('A');ylabel('D')
and so on.....
......
......
Now here start a tricky part in which I required help from experts like you guys. I do not want to do manual plotting for my matrix as it consists on 200 columns. So what I want to do a automatic plotting of matrix, so that it plot every column of matrix in subplots. But 200 subplot can not come in one figures, so it start automatically a new figure after subplots limit(let's say 3). Beside I also need to define 'xlabel, ylabel,legend' automatically with a header file 'colheaders'. Is it possible?

x = rand(10, 200);
myYLabel = char(64+randi(26, 200, 1));
nrows = 3;
ncols = 2;
for ii = 1:size(x, 2)
if nrows*ncols-mod(-ii, nrows*ncols) == 1
figure;
end
subplot(nrows, ncols, nrows*ncols-mod(-ii, nrows*ncols));
plot(x(:, ii));
ylabel(myYLabel(ii, :));
end

It seems to be an easy for-loop task.
I assume you know before how much subplots you want in each figure (let's say 3).
A = yourdatamatrix;
header = [{'A'}, {'B'}, {'C'}, {'D'}, {'E'}, {'F'}];
n = 6 %number of columns
i_figure = 1;
for ii=1:3:n-3
figure(ii)
subplot(3,1,1)
plot(A(:,1),A(:,ii+1),'ro'); grid on; box on; xlabel(header(1));ylabel(header(ii+1))
subplot(3,1,2)
plot(A(:,1),A(:,ii+2),'bo'); grid on; box on; xlabel(header(1));ylabel(header(ii+2))
subplot(3,1,3)
plot(A(:,1),A(:,ii+3),'go'); grid on; box on; xlabel(header(1));ylabel(header(ii+3))
end
I assume also you don't care about your figure number, otherwise just implement another counter.
Also be aware that the number of your columns+1 is divisible by 3.

Related

How to plot a multidimensional array in matlab?

I have a table as follows
system:index 2017_06_18 2017_06_19 2017_06_20 2017_06_21
2 612.8099664 1174.656713 1282.083251 815.3828357
3 766.4103726 1345.135952 1322.726083 749.998993
4 765.0230453 1411.669136 1350.437586 610.9541838
5 553.5858458 1374.14789 1152.086957 566.7924468
6 466.9780908 1311.903756 1060.494001 559.1982264
7 257.1162602 1270.182385 988.5455285 562.9224932
8 230.6611542 1310.971988 1001.548768 502.3266959
I want to plot a 2d-colormap representing system:index as y axis, dates as x axis and values under dates as colors. I tried with the following code but it did not give what I want.
clear
clc
filename = 'TurbidityDailyMean.xlsx';
data = xlsread(filename,'TurbidityDailyMean','A1:E8');
figure;
hold on
for i = 2:5
y = data(:,1);
x = data(:,i);
plot(x,y)
end
I need to map a colormap as mentioned above. But from what I tried it gives something else. And another fact is that I can't insert system:index and dates row into matlab with relevant data.
Thanks to my supervisor Dr.Kavinda,enter image description here the solution I adopted from him was as follows
data1 = csvread('TurbidityDailyMean.csv',1,1);
[mm,nn]=size(data1)
xx=ones(mm,nn);
yy=ones(mm,nn);
for j=1:nn
xx(:,j)=j;
end
for i=1:mm
yy(i,:)=i;
end
zz=data1;
h1=pcolor(xx,yy,zz);
shading flat
set(gcf,'color',[1,1,1])
axis([1 5 1 7]);
jet2=jet;
jet2(1,:)=1.0;
colormap(jet2)
caxis([0.0 0.13])
hold on
xlabel('Julian Day');
ylabel('y (?~1 km)');
colorb=colorbar;
set(get(colorb,'ylabel'),'String','Normalized Red Band Reflectance','fontsize',15,
'color', 'k');
set(get(colorb,'xlabel'),'fontsize',20, 'color', 'k');
grid on

plotting from cell array of different lengths

this might come as an eco in this forum but I couldn't find a solution that I could apply to my problem. I have a cell of res_A1 of size (1x500) and in each cell there is a vector (1xlength) where length varies. I would like to plot in the same graph every vector or maybe a handful of them. All lines can be in the same color. I have tried following but the graph make no sense
data=res_A1(1,:,end);
plot(cell2mat(data)');
Also I would like to plot the average of the 500 vectors, preferably this should be in the same graph in another color. Is there a nice way of doing this?
You can use cat to combine the vectors along the first dimension. Then you can pass the transpose of this matrix to plot and each column will be plotted as it's own plot.
plot(cat(1, data{:}).');
If we create some example data, this will yield.
data = arrayfun(#(x)rand(1,10), ones(1, 5), 'uni', 0);
plot(cat(1, data{:}).');
If you want specific ones (i.e. [1 3 5]), you can replace : above with the indices of the ones you want.
plot(cat(1, data{[1 3 5]}).');
If you want to plot the average, simply use mean on the result of the call to cat.
avg = mean(cat(1, data{:}), 1);
plot(avg);
And if you wanted it in the same plot:
alldata = cat(1, data{:});
avg = mean(alldata, 1);
% Plot all of the curves
plot(alldata.');
hold on
% Plot the average curve
plot(avg, 'LineWidth', 3, 'Color', [0.5 0.5 0.5], 'LineStyle', '--')
Update
If your data is all different lengths, You have two options, you could plot everything with a loop.
hax = axes;
hold(hax, 'on');
for k = 1:numel(data)
plot(data{k}, 'Parent', hax);
end
Or you could still try to combine everything into one matrix, padding with NaN values.
% Find the longest vector length
maxlength = max(cellfun(#(x)numel(x), data));
alldata = nan(maxlength, numel(data));
for k = 1:numel(data)
alldata(1:numel(data{k}),k) = data{k};
end
Then you can plot this and take the mean using nanmean.
plot(alldata);
avg = nanmean(alldata, 2);

Is it possible to plot rows of a matrix without a for loop?

I have a matrix that stores multiple functions in its rows each evaluated against the interval [0,20]. I'm running through a for loop to output them at the moment. Is there a better way of doing this or is this the only way of doing it in MATLAB?
h = 0.1;
xLine = 0:h:20;
nGrid = length(xLine);
nu = [ 1, 2, 3 ];
nNu = length(nu);
b = zeros(nNu,nGrid);
for i=1:nNu
b(i:i,1:nGrid) = besselj(nu(i), xLine);
end
hFig = figure(1);
hold on
set(hFig, 'Position', [1000 600 800 500]);
for i=1:nNu
plot(xLine, b(i:i,1:nGrid))
end
You can use plot vectorized. Specifically, you can supply b directly into plot but you need to make sure that the larger of the two dimensions in b matches the total number of elements in the vector xLine. This is what you have, so we're good. Therefore, because each unique signal occupies a row in your matrix, just supply b into your plot call and use it a single time.
hFig = figure(1);
hold on
set(hFig, 'Position', [1000 600 800 500]);
plot(xLine, b);
This will plot each row as a separate colour. If you tried doing this, you'll see that the plots are the same in comparison to the for loop approach.
Check out the documentation for plot for more details: http://www.mathworks.com/help/matlab/ref/plot.html
Replace for loop with:
plot(xLine, b(:,1:nGrid))
Note: I can't perfectly recall but some older versions of Matlab may want everything in columns and you'd want to transpose the matrices:
plot(xLine.', b(:,1:nGrid).')

Add lines of different lengths to plot in Matlab

In this trivial example I extract a portion of x to make y & y1. To plot y1 in the correct position I used NaN padding in the front. I'm wondering whether NaN padding is considered the best practice or is there some way to directly specify the X coordinate where I want the y1 line segment plotted?
figure(500);
hold off;
x = rand(1,100);
plot(x);
y = x(20:60)+3;
hold on;
plot(y);
y1 = horzcat(repmat(nan,1,19), (y+3));
plot(y1);
If your main goal is just to display the sub-set of data within the proper range, seems like you could just specify the x-range directly, like:
x_range = 20:60;
y = x(x_range)+3;
hold on;
plot(y);
plot(x_range, y+3);
grid on
Which gives the identical result you got using Nans:

bode plot discrepancy

I am plotting the following
Cu4 = tf([1 2], [1 2 6]);
[magCu4 phaseCu4 wout] = bode(Cu4,logspace(-2,7,300));
magCu4 = squeeze(magCu4);
phaseCu4 = squeeze(phaseCu4);
semilogx(wout,20*log10(magCu4)),grid;
hold on
bode(Cu4,'r')
I would expect that the semilogx plot would return an identical plot as 'bode'. however, this doesn't seem to be the case. Does anyone know what is going wrong here?
The difference is that you do not specify a frequency vector in your second call to bode so MATLAB chooses a default vector (in your code it had length of 46).
Instead you could try:
bode(Cu4,'r',logspace(-2,7,300))
Compare the plots made by the following code
[magCu4 phaseCu4 wout] = bode(Cu4,logspace(-2,7,300));
magCu4 = squeeze(magCu4);
figure(1);
semilogx(wout,20*log10(magCu4))
hold on;
bode(Cu4,'r')
hold off;
figure(2);
semilogx(wout,20*log10(magCu4))
hold on;
bode(Cu4,'r',logspace(-2,7,300))
hold off;