Matlab_ Plot the difference between two graphs - matlab

I am new to Matlab and I am struggling plotting the difference between these two graphs (subtract one plot from another) ... Can anyone help me?
% 2D plot of original target locations
X= double(xCoords);
Y= double(yCoords);
originalvalues = hist3([X(:) Y(:)],[30 40]);
imagesc(originalvalues)
contourf(originalvalues)
c= colorbar;
c.Label.String = 'Initial location';
axis equal
axis xy
xlabel('endCoordinatesx');
ylabel('endCoordinatesy');
title('2D Map of Original locations');
% 2D plot of final target locations
Xf= Design.endCoordinatesX;
Yf= Design.endCoordinatesY;
values = hist3(double([Xf(:) Yf(:)],[30 40]));
imagesc(values)
contourf(values)
c= colorbar;
c.Label.String = 'Final location';
axis equal
axis xy
xlabel('endCoordinatesx');
ylabel('endCoordinatesy');
title('2D Map of final locations');

If I understood well your problem, you want to making a third plot representing the difference between the two datasets.
What you have to do is to get common bins for all the histograms you calculate :
% find common centers for the two datasets
[~, centers] = hist3(cat(2,[X(:) ; Xf(:)],...
[Y(:) ; Yf(:)]),...
[30 40]);
% then you can calculate the histogram for each set of data :
originalvalues = hist3([X(:) Y(:) ], centers);
values = hist3([Xf(:) Yf(:)], centers);
% finaly, compute the difference between the two (now the bins are "aligned")
differenceValue = values - originalvalues;

Related

How to plot a histogram as a scatter plot in matlab?

The y axis should be frequency (which is the histogram part) while the x axis is the xdata used to plot the histogram. Essentially what I need is exactly a histogram but instead of bars, there should be points.
I'd do that using the histcounts command. It's like the histogram command, but instead of plotting the data, it returns the number in each bin and the bin edges. You can then plot that as points using the general plot command.
x = randn(1,1000); %Generate some data to plot
figure(1); clf;
subplot(2,1,1); hold on;
h = histogram(x,'normalization','probability');
title('Plotted as a histogram');
ylabel('Frequency');
subplot(2,1,2); hold on;
[N, edges] = histcounts(x,'normalization','probability');
centers = (edges(1:end-1) + edges(2:end))./2; %histcounts gives the bin edges, but we want to plot the bin centers
plot(centers,N,'ko');
title('Plotted as points');
ylabel('Frequency');

hist3 plot with additional z axis

The following code creates a 2D stacked histogram for two 2D distributions:
%%first dataset
x1 = 200 + 300.*rand(1000,1)'; %rand values between 0 and 200
y1 = 100 + 250.*rand(1000,1)'; %rand values between 100 and 500
%%secnd dataset
x2 = 100 + 200.*rand(1000,1)'; %rand values between 0 and 200
y2 = 200 + 400.*rand(1000,1)'; %rand values between 100 and 500
one = linspace(100,400,20);
two = linspace(100,500,20);
EDGES = {one, two}; %edges
[n1,c1] = hist3([x1' y1'],'Edges',EDGES);%first dataset
[n2,c2] = hist3([x2' y2'],'Edges',EDGES);%second dataset
figure('Color','w');
% plot the first data set
bh=bar3(n1);
% Loop through each row and shift bars upwards
for ii=1:length(bh)
zz = get(bh(ii),'Zdata');
kk = 1;
% Bars are defined by 6 faces(?), adding values from data2 will
% shift the bars upwards accordingly, I'm sure this could be made
% better!
for jj = 0:6:(6*length(bh)-6)
zz(jj+1:jj+6,:)=zz(jj+1:jj+6,:)+n2(kk,ii);
kk=kk+1;
end
%erase zero height bars
%# get the ZData matrix of the current group
Z = get(bh(ii), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(bh(ii), 'ZData',Z)
end
% Set face colour to blue for data1
set(bh,'FaceColor',[0 0 1]);
% Apply hold so that data2 can be plotted
hold on;
% Plot data2
bh=bar3(n2);
%erase zero height bars
for ii=1:numel(bh)
%# get the ZData matrix of the current group
Z = get(bh(ii), 'ZData');
%# row-indices of Z matrix. Columns correspond to each rectangular bar
rowsInd = reshape(1:size(Z,1), 6,[]);
%# find bars with zero height
barsIdx = all([Z(2:6:end,2:3) Z(3:6:end,2:3)]==0, 2);
%# replace their values with NaN for those bars
Z(rowsInd(:,barsIdx),:) = NaN;
%# update the ZData
set(bh(ii), 'ZData',Z)
end
% Set face color to red
set(bh,'FaceColor',[1 0 0]);
%set ticks
set(gca,'XTick',1:6:numel(one),'XTickLabel',one(1:6:end))
set(gca,'YTick',1:6:numel(one),'YTickLabel',one(1:6:end))
view(20,40)
%labels
xlabel('x')
ylabel('y')
zlabel('z')
%set transparency
set(gcf,'renderer','opengl');
set(get(gca,'child'),'FaceAlpha',0.8);
set(get(gca,'child'),'EdgeAlpha',0.3);
A first issue is the transparency (but I think it is a problem of my matlab version 2014a, so I am not bothered by that). It just makes all blurry.
My question is how to add a mesh plot on the same picture. The code creating the meshes is the following:
%create surface I want to plot
[X,Y] = meshgrid(one,two);
inds1=find(X(:).*Y(:)<.3e5);%condition
inds2=find(X(:).*Y(:)>.3e5);
I=Y./X.^2;%first surface
I(inds1)=NaN;%second surface
figure('Color','w');hold on
mesh(X,Y,I,'FaceColor',[0 0 1],'EdgeColor','none')
I(:,:)=NaN;
I(inds1)=Y(inds1)./X(inds1);%second surface
mesh(X,Y,I,'FaceColor',[1 0 0],'EdgeColor','none')
alpha(.5)
grid on
view(20,40)
%labels
xlabel('x')
ylabel('y')
zlabel('z')
The domain of the histograms and the meshes are the same. So I just need to add an extra z-axis on the first figure.
I tried substituting figure('Color','w');hold on in the second code with AxesH = axes('NextPlot', 'add');, but I was really wrong about that:
That just overlayed the two figures..
I also tried something along the lines of:
%add axis
axesPosition = get(gca,'Position'); %# Get the current axes position
hNewAxes = axes('Position',axesPosition,... %# Place a new axes on top...
'Color','none',... %# ... with no background color
'ZLim',[0 400],... %# ... and a different scale
'ZAxisLocation','right',... %# ... located on the right
'XTick',[],... %# ... with no x tick marks
'YTick',[],... %# ... with no y tick marks
'Box','off');
but it is not feasible because the property ZAxisLocation does not exist.
Does anyone know how to add the z-axis?
Also, if you have other comments on how to ameliorate the code, they're welcome!
acknowledgements
2d stacked histogram:https://stackoverflow.com/a/17477348/3751931
erasing the zero values in the hist plot: https://stackoverflow.com/a/17477348/3751931
I now think that this is not yet possible (http://www.mathworks.com/matlabcentral/answers/95949-is-there-a-function-to-include-two-3-d-plots-with-different-z-axes-on-the-same-plot-area-similar-to).
So I just added a fake axis:
[X,Y] = meshgrid(one,two);
inds1=find(X(:).*Y(:)<.3e5);%condition
inds2=find(X(:).*Y(:)>.3e5);
s=Y./X.^2;%first surface
s(inds1)=NaN;%second surface
%mesh(X,Y,I,'FaceColor',[0 0 1],'EdgeColor','none')
mesh((X-min(min(X)))/max(max(X-min(min(X))))*20,(Y-min(min(Y)))/max(max(Y-min(min(Y))))*20,...
s/max(max(s))*max(max(n1))+max(max(n1)),'FaceColor','g','EdgeColor','none','facealpha',.5)
s(:,:)=NaN;
s(inds1)=Y(inds1)./X(inds1);%second surface
%mesh(X,Y,I,'FaceColor',[1 0 0],'EdgeColor','none')
mesh((X-min(min(X)))/max(max(X-min(min(X))))*20,(Y-min(min(Y)))/max(max(Y-min(min(Y))))*20,...
s/max(max(s))*max(max(n1))+max(max(n1)),'FaceColor','y','EdgeColor','none','facealpha',.5)
alpha(.5)
grid on
%add fake z axis
line([20 20],[1 1],[max(max(n1))-min(min(s)) 20],...
'color','g','linewidth',2)
% text(20*ones(1,5),zeros(1,5),linspace(max(max(n1))-min(min(I)),20,5),...
% num2str(linspace(0,max(max(I)),5)),'color','g')
z=linspace(max(max(n1))-min(min(s)),20,5);
txto=linspace(0,max(max(s)),5);
for ii=1:5
line([20 20.3],[1 1],[z(ii) z(ii)],'color','g')%ticks
text(20,0,z(ii),num2str(txto(ii)),'color','g')%ticklabel
end
text(19.8,1,21,'s','color','g')%label
Over all the code is quite ugly and needs a lot of tuning..

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.

Plotting a 3D graph of normalized prices in MatLab

I'm doing Gaussian processes and I calculated a regression per year from a given matrix where each row represents a year , so the code is:
M1 = MainMatrix; %This is the given Matrix
ker =#(x,y) exp(-1013*(x-y)'*(x-y));
[ns, ms] = size(M1);
for N = 1:ns
x = M1(N,:);
C = zeros(ms,ms);
for i = 1:ms
for j = 1:ms
C(i,j)= ker(x(i),x(j));
end
end
u = randn(ms,1);
[A,S, B] = svd(C);
z = A*sqrt(S)*u; % z = A S^.5 u
And I wanna plotting each regression in a Graph 3D as the below:
I know that plot is a ribbon, but I have not idea how can I do that
The desired plot can be generated without the use of ribbon. Just use a surf-plot for all the prices and a fill3-plot for the plane at z=0. The boundaries of the plane are calculated from the actual limits of the figure. Therefore we need to set the limits before plotting the plane. Then just some adjustments are needed to generate almost the same appearance.
Here is the code:
% generate some data
days = (1:100)';
price = days*[0.18,-0.08,0.07,-0.10,0.12,-0.08,0.05];
price = price + 0.5*randn(size(price));
years = 2002+(1:size(price,2));
% prepare plot
width = 0.6;
X = ones(size(price,1),1)*0.5;
X = [-X,X]*width;
figure; hold on;
% plot all 'ribbons'
for i = 1:size(price,2)
h = surf([days,days],X+years(i),[price(:,i),price(:,i)]);
set(h,'MeshStyle','column');
end
% set axis limits
set(gca,'ZLim',[-20,20]);
% plot plane at z=0
limx = get(gca,'XLim');
limy = get(gca,'YLim');
fill3(reshape([limx;limx],1,[]),[flip(limy),limy],zeros(1,4),'g','FaceAlpha',0.2)
% set labels
xlabel('Day of trading')
ylabel('Year')
zlabel('Normalized Price')
% tweak appearance
set(gca,'YTick',years);
set(gca,'YDir','reverse');
view([-38,50])
colormap jet;
grid on;
%box on;
This is the result:
That's a ribbon plot with an additional surface at y=0 which can be drawn with fill3

Matlab:Make a contour plot with 3 vectors

I have 3 vectors of data, X (position), Y (position) both of which are not regularly spaced, and Z(value of interest at each location). I tried contourf, which doesn't work because it needs a matrix for Z input.
You can also use griddata.
%Generate random data
x = rand(30,1);
y = rand(30,1);
z = rand(30,1);
%Create regular grid across data space
[X,Y] = meshgrid(linspace(min(x),max(x),n), linspace(min(y),max(y),n))
%create contour plot
contour(X,Y,griddata(x,y,z,X,Y))
%mark original data points
hold on;scatter(x,y,'o');hold off
For a contour plot you actually need either a matrix of z values, or a set (vector) of z-values evaluated on a grid. You cannot define contours using isolated Z values at (X,Y) points on the grid (i.e. what you claim you have).
You need to have the generating process (or function) provide values for a grid of (x,y) points.
If not, then you can create a surface from nonuniform data as #nate correctly pointed out, and then draw the contours on that surface.
Consider the following (random) example:
N = 64; % point set
x = -2 + 4*rand(N,1); % random x vector in[-2,2]
y = -2 + 4*rand(N,1); % random y vector in[-2,2]
% analytic function, or z-vector
z = x.*exp(-x.^2-y.^2);
% construct the interpolant function
F = TriScatteredInterp(x,y,z);
t = -2:.25:2; % sample uniformly the surface for matrices (qx, qy, qz)
[qx, qy] = meshgrid(t, t);
qz = F(qx, qy);
contour(qx, qy, qz); hold on;
plot(x,y,'bo'); hold off
The circles correspond to the original vector points with values (x,y,z) per point, the contours on the contours of the interpolant surface.