How to plot histogram of columns of a matrix in MATLAB? - matlab

I have to plot a histogram of each column of MatrixE1. How can I go about doing this? This is what I have written so far.
% Create a random 5 x 3 matrix filled with random values between 0 and 10
a0 = 0;
b0 = 10;
r = a0 + (b0-a0).*rand(1,1);
matrixA = [randi([0 10]) randi([0 10]) randi([0 10]); randi([0 10]) randi([0 10]) randi([0 10]); randi([0 10]) randi([0 10]) randi([0 10]); randi([0 10]) randi([0 10]) randi([0 10]); randi([0 10]) randi([0 10]) randi([0 10])]
% Create identity matrix 3 x 3
matrixB = eye(3,3)
% Create new submatrix of A with the last 3 rows
matrixC = matrixA(end-2 : end, :)
% Pair wise multiplication of C and B
matrixD = times(matrixC, matrixB)
% Concatenate Matrix A and D
matrixE1 = [matrixA ; matrixD]
% Plot histogram of columns.
matrixColumn1 = matrixE1(1 : end , end-2: end-2);
matrixFColumn2 = matrixE1(1 : end, end -1 : end-1);
matrixFColumn3 = matrixE1(1 : end, end : end);

You can access each of your coloumns in matrixE1 like this:
firstCol = matrixE1(:,1);
secondCol = matrixE1(:,2);
thirdCol = matrixE1(:,3);
...and then you can simply use comand hist() to plot histograms. You would plot histogram of first coloumn in matrixE1 as:
hist(firstCol);
And if I understand your second question:
''What would I do? hist(??). How can I get one histogram of all the columns of matrixE1? Should I do hist(matrixE1)?''
You can simply use command hold on after ploting histogram of one coloumn. Then plot another histogram on the same plot. For example if you want to plot histogram of first and second coloumn from matrixE1 to the same plot, you would type:
hist(firstCol);
hold on;
hist(secondCol);

>> v1=randn(1000,1); % zero mean, unity stdev
>> v2=randn(1000,1)+1; % mean at one, unity stdev
>> V=[v1 v2]; % 1000 x 2 matrix
>> hist(V,100); % 100 bins
>> legend('v1', 'v2');

There is another, simpler but computationally more expensive way:
plotmatrix(A)
For any matrix A this will produce a m-by-n plot of scatterplots of all pairwise combinations of your input matrix (do not do this for large matrices, larger than you could fit on your screen).
What you gain on top are histograms along the main diagonal of the plotmatrix.

Adding this answer due to other answers (1, 2) using outdated function hist.
MATLAB recommends avoiding the use of hist and now favors histogram (source). The changeover is straightforward.
% MATLAB R2019a
% Sample Data
NumPoints = 2000;
a1 = 10*rand(NumPoints,1);
a2 = wblrnd(3,7,NumPoints,1);
a3 = 7 + 0.75*randn(NumPoints,1);
A = [a1 a2 a3]; % Data Matrix
% Implement Sturges Rule for n<=500, Scott's Rule for n>500
nbinsh =#(n) ceil((1 + 3.3*log10(n))*(n<=500) + ((5/3)*(n^(1/3)))*(n>500));
NumBins = nbinsh(NumPoints);
numCols = size(A,2);
% Plot
figure, hold on
for k = 1:numCols
histogram(A(:,k),'NumBins',NumBins,'DisplayName',['Col ' num2str(k)]);
end
legend('show')
You can adjust from frequency (counts) to probability or probability density function depending on the application needs with the Normalization property (see documentation here).

Related

How to find a value which is bigger than the maximum point from point set? (Function to find Cubic Spline Interpolation by Matlab)

I have written a Matlab code to construct a Cubic Runout Spline, with a figure to display my data. But how can i show a data which is not in my data group ex.f(2010) in my figure. I have an idea. I can show t is valid after 2000, which t=2010, but I have no idea to start it.
clear; clc;
t= [1850, 1875, 1900, 1925, 1950, 1975, 2000];
y= [285.2, 288.6, 295.7, 305.3, 311.3, 331.36, 369.64];
N= length(t); %number of points I want
n=N-1 ; % number of subintervals
h=(t(N)-t(1))/n; %step size
A=[1,1,1,0],B=[2,0,0,0,2],C=[0,1,1,1];
Trid=diag(4*ones(1,n-1))+diag(A,-1)+diag(B)+diag(C,1);
for i=1:n-1
f(i)= 6/h^2*(y(i+2)-2*y(i+1)+y(i));
end
f=f';
w=inv(Trid)*f;%since sigma 1 and sigma n+1 are both 0, we need to add 0 in the beginning and also in the end of then matrix
sigma=[0;w;0];%it is a nx1 matrix, be careful.
for i=1:n
d(i)=y(i);
b(i)=sigma(i)/2;
a(i)=(sigma(i+1)-sigma(i))/(6*h);
c(i)=(y(i+1)-y(i))/h-h/6*(2*sigma(i)+sigma(i+1));
end
r= 25; %subsubintervals for t ex. between 1850 and 1875, here i seperate it into 1 years per slot
hh=h/r; %step size of subsubintervals
x=t(1):hh:t(N);
for i=1:n
for j=r*(i-1)+1:r*i
s(j)=a(i)*(x(j)-t(i))^3+b(i)*(x(j)-t(i))^2+c(i)*(x(j)-t(i))+d(i);
end
end
s(r*n+1)=y(N);
plot(t,y,'o')
hold on
plot(x,s,'-x')
hold off
What you are asking is extrapolation. You did the interpolation, which is good. For the extrapolation, just continue the last segment's cubic equation.
s(r*n+1)=y(N);
s_orig_len = length(s); %% new
plot(t,y,'o')
hold on
plot(x,s,'-x')
% hold off %%% there is more to plot!
% %% All new lines below
i_last = 6;
i_next = 7;
t = [t 2026];
x_extrapolation = x(end):t(end);
x = [x x_extrapolation];
for j = r*(i_next-1)+1:r*i_next + 3
s(j)=a(i_last)*(x(j)-t(i_last))^3+b(i_last)*(x(j)-t(i_last))^2+c(i_last)*(x(j)-t(i_last))+d(i_last);
end
plot(x_extrapolation, s(s_orig_len+1:end), '-b', 'LineWidth',2)
hold off;
I hope this helps.

Constrained linear least squares not fitting data

I am trying to fit a 3D surface polynomial of n-degrees to some data points in 3D space. My system requires the surface to be monotonically increasing in the area of interest, that is the partial derivatives must be non-negative. This can be achieved using Matlab's built in lsqlin function.
So here's what I've done to try and achieve this:
I have a function that takes in four parameters;
x1 and x2 are my explanatory variables and y is my dependent variable. Finally, I can specify order of polynomial fit. First I build the design matrix A using data from x1 and x2 and the degree of fit I want. Next I build the matrix D that is my container for the partial derivatives of my datapoints. NOTE: the matrix D is double the length of matrix A since all datapoints must be differentiated with respect to both x1 and x2. I specify that Dx >= 0 by setting b to be zeroes.
Finally, I call lsqlin. I use "-D" since Matlab defines the function as Dx <= b.
function w_mono = monotone_surface_fit(x1, x2, y, order_fit)
% Initialize design matrix
A = zeros(length(x1), 2*order_fit+2);
% Adjusting for bias term
A(:,1) = ones(length(x1),1);
% Building design matrix
for i = 2:order_fit+1
A(:,(i-1)*2:(i-1)*2+1) = [x1.^(i-1), x2.^(i-1)];
end
% Initialize matrix containing derivative constraint.
% NOTE: Partial derivatives must be non-negative
D = zeros(2*length(y), 2*order_fit+1);
% Filling matrix that holds constraints for partial derivatives
% NOTE: Matrix D will be double length of A since all data points will have a partial derivative constraint in both x1 and x2 directions.
for i = 2:order_fit+1
D(:,(i-1)*2:(i-1)*2+1) = [(i-1)*x1.^(i-2), zeros(length(x2),1); ...
zeros(length(x1),1), (i-1)*x2.^(i-2)];
end
% Limit of derivatives
b = zeros(2*length(y), 1);
% Constrained LSQ fit
options = optimoptions('lsqlin','Algorithm','interior-point');
% Final weights of polynomial
w_mono = lsqlin(A,y,-D,b,[],[],[],[],[], options);
end
So now I get some weights out, but unfortunately they do not at all capture the structure of the data. I've attached an image so you can just how bad it looks. .
I'll give you my plotting script with some dummy data, so you can try it.
%% Plot different order polynomials to data with constraints
x1 = [-5;12;4;9;18;-1;-8;13;0;7;-5;-8;-6;14;-1;1;9;14;12;1;-5;9;-10;-2;9;7;-1;19;-7;12;-6;3;14;0;-8;6;-2;-7;10;4;-5;-7;-4;-6;-1;18;5;-3;3;10];
x2 = [81.25;61;73;61.75;54.5;72.25;80;56.75;78;64.25;85.25;86;80.5;61.5;79.25;76.75;60.75;54.5;62;75.75;80.25;67.75;86.5;81.5;62.75;66.25;78.25;49.25;82.75;56;84.5;71.25;58.5;77;82;70.5;81.5;80.75;64.5;68;78.25;79.75;81;82.5;79.25;49.5;64.75;77.75;70.25;64.5];
y = [-6.52857142857143;-1.04736842105263;-5.18750000000000;-3.33157894736842;-0.117894736842105;-3.58571428571429;-5.61428571428572;0;-4.47142857142857;-1.75438596491228;-7.30555555555556;-8.82222222222222;-5.50000000000000;-2.95438596491228;-5.78571428571429;-5.15714285714286;-1.22631578947368;-0.340350877192983;-0.142105263157895;-2.98571428571429;-4.35714285714286;-0.963157894736842;-9.06666666666667;-4.27142857142857;-3.43684210526316;-3.97894736842105;-6.61428571428572;0;-4.98571428571429;-0.573684210526316;-8.22500000000000;-3.01428571428571;-0.691228070175439;-6.30000000000000;-6.95714285714286;-2.57232142857143;-5.27142857142857;-7.64285714285714;-2.54035087719298;-3.45438596491228;-5.01428571428571;-7.47142857142857;-5.38571428571429;-4.84285714285714;-6.78571428571429;0;-0.973684210526316;-4.72857142857143;-2.84285714285714;-2.54035087719298];
% Used to plot the surface in all points in the grid
X1 = meshgrid(-10:1:20);
X2 = flipud(meshgrid(30:2:90).');
figure;
for i = 1:4
w_mono = monotone_surface_fit(x1, x2, y, i);
y_nr = w_mono(1)*ones(size(X1)) + w_mono(2)*ones(size(X2));
for j = 1:i
y_nr = w_mono(j*2)*X1.^j + w_mono(j*2+1)*X2.^j;
end
subplot(2,2,i);
scatter3(x1, x2, y); hold on;
axis tight;
mesh(X1, X2, y_nr);
set(gca, 'ZDir','reverse');
xlabel('x1'); ylabel('x2');
zlabel('y');
% zlim([-10 0])
end
I think it may have something to do with the fact that I haven't specified anything about the region of interest, but really I don't know. Thanks in advance for any help.
Alright I figured it out.
The main problem was simply an error in the plotting script. The value of y_nr should be updated and not overwritten in the loop.
Also I figured out that the second derivative should be monotonically decreasing. Here's the updated code if anybody is interested.
%% Plot different order polynomials to data with constraints
x1 = [-5;12;4;9;18;-1;-8;13;0;7;-5;-8;-6;14;-1;1;9;14;12;1;-5;9;-10;-2;9;7;-1;19;-7;12;-6;3;14;0;-8;6;-2;-7;10;4;-5;-7;-4;-6;-1;18;5;-3;3;10];
x2 = [81.25;61;73;61.75;54.5;72.25;80;56.75;78;64.25;85.25;86;80.5;61.5;79.25;76.75;60.75;54.5;62;75.75;80.25;67.75;86.5;81.5;62.75;66.25;78.25;49.25;82.75;56;84.5;71.25;58.5;77;82;70.5;81.5;80.75;64.5;68;78.25;79.75;81;82.5;79.25;49.5;64.75;77.75;70.25;64.5];
y = [-6.52857142857143;-1.04736842105263;-5.18750000000000;-3.33157894736842;-0.117894736842105;-3.58571428571429;-5.61428571428572;0;-4.47142857142857;-1.75438596491228;-7.30555555555556;-8.82222222222222;-5.50000000000000;-2.95438596491228;-5.78571428571429;-5.15714285714286;-1.22631578947368;-0.340350877192983;-0.142105263157895;-2.98571428571429;-4.35714285714286;-0.963157894736842;-9.06666666666667;-4.27142857142857;-3.43684210526316;-3.97894736842105;-6.61428571428572;0;-4.98571428571429;-0.573684210526316;-8.22500000000000;-3.01428571428571;-0.691228070175439;-6.30000000000000;-6.95714285714286;-2.57232142857143;-5.27142857142857;-7.64285714285714;-2.54035087719298;-3.45438596491228;-5.01428571428571;-7.47142857142857;-5.38571428571429;-4.84285714285714;-6.78571428571429;0;-0.973684210526316;-4.72857142857143;-2.84285714285714;-2.54035087719298];
% Used to plot the surface in all points in the grid
X1 = meshgrid(-10:1:20);
X2 = flipud(meshgrid(30:2:90).');
figure;
for i = 1:4
w_mono = monotone_surface_fit(x1, x2, y, i);
% NOTE: Should only have 1 bias term
y_nr = w_mono(1)*ones(size(X1));
for j = 1:i
y_nr = y_nr + w_mono(j*2)*X1.^j + w_mono(j*2+1)*X2.^j;
end
subplot(2,2,i);
scatter3(x1, x2, y); hold on;
axis tight;
mesh(X1, X2, y_nr);
set(gca, 'ZDir','reverse');
xlabel('x1'); ylabel('x2');
zlabel('y');
% zlim([-10 0])
end
And here's the updated function
function [w_mono, w] = monotone_surface_fit(x1, x2, y, order_fit)
% Initialize design matrix
A = zeros(length(x1), 2*order_fit+1);
% Adjusting for bias term
A(:,1) = ones(length(x1),1);
% Building design matrix
for i = 2:order_fit+1
A(:,(i-1)*2:(i-1)*2+1) = [x1.^(i-1), x2.^(i-1)];
end
% Initialize matrix containing derivative constraint.
% NOTE: Partial derivatives must be non-negative
D = zeros(2*length(y), 2*order_fit+1);
for i = 2:order_fit+1
D(:,(i-1)*2:(i-1)*2+1) = [(i-1)*x1.^(i-2), zeros(length(x2),1); ...
zeros(length(x1),1), -(i-1)*x2.^(i-2)];
end
% Limit of derivatives
b = zeros(2*length(y), 1);
% Constrained LSQ fit
options = optimoptions('lsqlin','Algorithm','active-set');
w_mono = lsqlin(A,y,-D,b,[],[],[],[],[], options);
w = lsqlin(A,y);
end
Finally a plot of the fitting (Have used a new simulation, but fit also works on given dummy data).

Matlab plot: remove connecting line between disconnected regions?

Assume you have 1000 indexed datapoints, with two labels grouped into region1 and region2. Here is an example of how to generate such random data
indices = 1:1000;
data = zeros(size(indices));
% some regions of data
region1 = [50:100 200:340 450:500 670:980];
region2 = setdiff(indices, region1);
% generating random data
data(region1) = rand(size(region1)) + 1;
data(region2) = rand(size(region2));
Now, if I plot these two regions I get a plot shown below
The code to generate the plot
% plotting
figure(1);
cla(gca);
hold on;
plot(region1, data(region1));
plot(region2, data(region2));
hold off;
Now the question: Is there an elegant way of removing the connecting lines between the disconnected data regions, without doing much data manipulation? I still want to use the solid line linestyle, or have a look similar to that.
If you make the x or y values into NaN then they wont be plotted. Since you have two complimentary regions, you can use them to set values to NaN...
% Two vectors which each cover ALL elements in "data", but with NaN where
% the other region is to be plotted. As per example, indices=1:1000;
r1 = 1:1000; r1(region2) = NaN;
r2 = 1:1000; r2(region1) = NaN;
% Plot all data for both lines, but NaNs wont show.
figure(1); clf;
hold on;
plot(r1, data);
plot(r2, data);
hold off;
Output:
Turns out if you represent regions as a vector of the same length as x and y with integer values representing the index of the region (e.g. regions = [1 1 1 2 2 1 1 1 ..]), there is an elegant one-linear that does the job for an arbitrary number of regions. Here is an example
% Generating test data
x = 1:1000;
y = sin(x/100) + rand(1, 1000);
regions = repelem([1 2 3 1 2 3 1 2 3 3], repelem(100, 10)); % a [1 x 1000] vector
% Plotting
plot(bsxfun(#rdivide, x(:), bsxfun(#eq, regions(:), unique(regions(:))')), y(:));
Here, I am building the matrix for x with values that should not be plotted being Inf, due to the #rdivide division by 0. The result is the following.
I hope this will be helpful for someone in the future.

Plotting a cell array

I need to plot a cell array with the following format in Matlab:
{[vector1], [vector2], ...}
Into a 2D graph with the index of the vector as the y and the vector as the x
([vector1], 1), ([vector2], 2), ...
Here's a simple option:
% some arbitrary data:
CellData = {rand(10,1)*50,rand(10,1)*50,rand(10,1)*50};
% Define x and y:
x = cell2mat(CellData);
y = ones(size(x,1),1)*(1:size(x,2));
% plot:
plot(x,y,'o')
ylim([0 size(x,2)+1])
so you plot each vector of x on a separate y value:
It will work as long as your cell array is just a list of vectors.
EDIT: For non equal vectors
You'll have to use a for loop with hold:
% some arbitrary data:
CellData = {rand(5,1)*50,rand(6,1)*50,rand(7,1)*50,rand(8,1)*50,rand(9,1)*50};
figure;
hold on
for ii = 1:length(CellData)
x = CellData{ii};
y = ones(size(x,1),1)*ii;
plot(x,y,'o')
end
ylim([0 ii+1])
hold off
Hope this answers your question ;)
Here's my (brute force) interpretation of your request. There are likely more elegant solutions.
This code generates a dot plot that puts the values from the vectors at each index on the y axis—bottom to top. It can accommodate vectors of different lengths. You could make it a dot plot of vector distributions, but you might need to add some jitter to the x value, if multiple occurrences of identical or nearly identical values are possible.
% random data--three vectors from range 1:10 of different lengths
for i = 1:3
dataVals{i} = randi(10,randi(10,1),1);
end
dotSize = 14;
% plot the first vector with dots and increase the dot size
% I happen to like filled circles for this, and this is how I do it.
h = plot(dataVals{1}, ones(length(dataVals{1}), 1),'.r');
set(h,'markers', dotSize);
ax = gca;
axis([0 11 0 4]); % set axis limits
% set the Y axis labels to whole numbers
ax.YTickLabel = {'','','1','','2','','3','','',}';
hold on;
% plot the rest of the vectors
for i=2:length(dataVals)
h = plot(dataVals{i}, ones(length(dataVals{i}),1)*i,'.r');
set(h, 'markers', dotSize);
end
hold off
Without any data this is the best I can come up with for what you want:
yourCell = {[0,0,0],[1,1,1],[2,2,2]}; % 1x3 cell
figure;
plot(cell2mat(yourCell));
ylabel('Vector Values');
xlabel('Index of Vector');
It makes a plot like this:
Hope this helps.

Non-uniform axis of imagesc() in Matlab

Question: is it possible to illustrate an image on non-uniform axis?
Details:
I need to illustrate a multidimensional timeseries as an image. But the time grid of this timeseries is very non-uniform. Here is an example:
m = 10;
n = 3;
t = sort(rand(m, 1)); % non-uniform time
values = randn(m, n); % some random values
The figure, plot(t, values); handles it well.
But imagesc() converts t into uniform time between t(1) and t(end) according to documentation:
imagesc(x,y,C) displays C as an image and specifies the bounds of the
x- and y-axis with vectors x and y.
Therefore, the command:
figure, imagesc(t, 1 : n, values'); colorbar;
illustrates the image on uniform time grid.
Edit: It's possible to re-sample the timeseries with higher uniform resolution. But my timeseries is already very large.
There is pcolor function in MATLAB. This function does exactly what you're asking.
m = 10;
n = 3;
t = sort(rand(m, 1)); % non-uniform time
values = randn(m, n); % some random values
figure
plot(t, values);
figure
pcolor(t, 1 : n, values');
colorbar;
try uimagesc from the file exchange.
Solution
Try using surface for non-uniform spacing.
First, create a 3D xyz surface of the same size as your input data:
m = 10;
n = 3;
t = sort(rand(m, 1)); % non-uniform time
values = randn(m, n); % some random values
x = repmat(t,1,n);
y = repmat(1:n,m,1);
z = zeros(size(y));
Then, colormap your values. There is a nice tool posted to the mathworks file exchange, real2rgb, that can do this for you:
cdata = real2rgb(values); % Where size(cdata) = [m n 3]
Lastly, plot the surface. You can even get fancy and set the transparency.
surface(x,y,z,cdata,'EdgeColor','none','FaceColor','texturemap',...
'CDataMapping','direct');
alpha(0.3)