1

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

Community
  • 1
  • 1
shamalaia
  • 2,282
  • 3
  • 23
  • 35

1 Answers1

0

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..

shamalaia
  • 2,282
  • 3
  • 23
  • 35