MatLab:从采样数据中创建3D直方图

时间:2014-05-28 09:36:30

标签: matlab 3d histogram sample-data

我在数组transitions=zeros(101,101)的区间[0,1]中采样了数据,我想将其绘制为3D直方图。 transitions填充的数据类似于此主题末尾提供的示例数据。

第一列是第一个观察到的变量X,第二列是第二个变量Y,第三列是标准化频率。即对于第一行:观察到的变量对(0,0)的归一化频率为0.9459。因此(0,Y)的归一化频率之和为1

我尝试使用以下代码制作(排序)3D直方图:

        x_c = (transitions(:,1) * 100)+1;
        y = (transitions(:,2) * 100)+1;
        z = transitions(:,4);
        %A = zeros(10,10);
        A = zeros(max(x_c),max(y));
        for i = 1:length(x_c)
            try
                    if(z(i)>0)
                        A(int32(x_c(i)), int32(y(i))) = abs(log(z(i)));
                    else
                        % deal with exceptions regarding log(0)
                        A(int32(x_c(i)), int32(y(i))) = 0;
                    end
            catch
                disp('');
            end
        end
        bar3(A);

但是,由于它是在离散空间A中的采样数据,因此输出如下图所示。这在某种程度上是误导的,因为图中存在“间隙”(对于我没有采样数据的坐标,z值= 0)。我宁愿将采样数据分配到相应的图中,从而产生“真实的”3D直方图。

False histogram

顺便说一下,由于我'创建A的'hack',x,y和z比例也不正确。 3D直方图的轴(全部三个)应位于[0,1]的区间内。

ans =

     0         0    0.9459
     0    0.0500    0.0256
     0    0.1000    0.0098
     0    0.1100    0.0004
     0    0.1500    0.0055
     0    0.1600    0.0002
     0    0.2000    0.0034
     0    0.2100    0.0001
     0    0.2500    0.0024
     0    0.2600    0.0001
     0    0.3000    0.0018
     0    0.3200    0.0000
     0    0.3700    0.0000
     0    0.4000    0.0010
     0    0.4200    0.0000
     0    0.4500    0.0007
     0    0.5000    0.0007
     0    0.5300    0.0000
     0    0.5500    0.0005
     0    0.6000    0.0005
     0    0.6300    0.0000
     0    0.7000    0.0002
     0    0.7400         0
     0    0.7500    0.0003
     0    0.7900    0.0000
     0    0.8000    0.0002
     0    0.8400    0.0000
     0    0.8500    0.0002
     0    0.8900    0.0000
     0    0.9000    0.0002
     0    0.9500    0.0001
     0    1.0000    0.0001
0.0500         0    0.0235
0.0500    0.0500    0.0086
0.0500    0.1000    0.0045

     .         .         .
     .         .         .
     .         .         .
     .         .         .
     .         .         .
0.9500    0.9000    0.0035
0.9500    0.9500    0.0066
0.9500    1.0000    0.0180
1.0000         0    0.0001
1.0000    0.0500    0.0001
1.0000    0.1000    0.0001
1.0000    0.1100    0.0000
1.0000    0.1500    0.0001
1.0000    0.1600    0.0000
1.0000    0.2000    0.0001
1.0000    0.2100    0.0000
1.0000    0.2500    0.0001
1.0000    0.2600    0.0000
1.0000    0.3000    0.0001
1.0000    0.3200    0.0000
1.0000    0.3700    0.0000
1.0000    0.4000    0.0002
1.0000    0.4200         0
1.0000    0.4500    0.0002
1.0000    0.5000    0.0003
1.0000    0.5300    0.0000
1.0000    0.5500    0.0004
1.0000    0.6000    0.0004
1.0000    0.6300    0.0000
1.0000    0.7000    0.0007
1.0000    0.7400    0.0000
1.0000    0.7500    0.0010
1.0000    0.7900    0.0000
1.0000    0.8000    0.0015
1.0000    0.8400    0.0001
1.0000    0.8500    0.0024
1.0000    0.8900    0.0002
1.0000    0.9000    0.0042
1.0000    0.9500    0.0111
1.0000    1.0000    0.3998

2 个答案:

答案 0 :(得分:2)

我通过处理非聚合数据找到了解决方案。特别是,数据集transitions的每一行都包含XY的一个观察。我使用下面的代码生成标准化的3D直方图(和2D地图),如下所示:

nromalized 3D histogram

function createHistogram(transitions)
   uniqueValues = unique(transitions(:,1));
   biases = cell(numel(uniqueValues),1);

   for i = 1:numel(uniqueValues)
       start = min(find(transitions(:,1) == uniqueValues(i)));
       stop = max(find(transitions(:,1) == uniqueValues(i)));
       biases(i) = mat2cell(transitions(start:stop,2));
   end

   combinedBiases = padcat(biases{1},biases{2},biases{3},biases{4},...
       biases{5},biases{6},biases{7},biases{8},biases{9},biases{10},...
       biases{11},biases{12},biases{13},biases{14},biases{15},biases{16},...
       biases{17},biases{18},biases{19});

   bins = 0:0.1:1;
   [f, x] = hist(combinedBiases, bins);

   %
   % normalize
   %
   for i = 1:numel(f(1,:))
       for j = 1:numel(f(:,i))
            f(j,i) = f(j,i)/numel(biases{i});
       end
   end
   bHandle = bar3(x, f);
   ylim([-0.04,1.04])
   for k = 1:length(bHandle)
        zdata = get(bHandle(k),'ZData');
        set(bHandle(k),'CData',zdata, 'FaceColor','interp');
   end
   colormap('autumn');
   hcol = colorbar();
   axis('square');
   cpos=get(hcol,'Position');
   cpos(4)=cpos(4)/3; % Halve the thickness
   cpos(2)=0.4; % Move it down outside the plot#
   cpos(1)=0.82;
   set(hcol, 'Position',cpos);
   xlabel('Enrollment biases');
   ylabel('Aging biases');
   zlabel('Bias transition probability');
   title(strcat('Probability mass function of bias transitions (', device,')'));
   set(gca,'XTick',0:2:20);
   set(gca,'XTickLabel',0:0.1:1);
   print('-dpng','-r600',strcat('tau_PMF3D_enrollment-ageing-', device));
   view(2);
   cpos(1)=0.84;
   set(hcol, 'Position',cpos);
   print('-dpng','-r600',strcat('tau_PMF2D_enrollment-ageing-', device));
end

答案 1 :(得分:0)

从问题的评论中可以看出,您想要表示每个bin计数的值。如果是这样,另一种解决方案是使用hist3使用正确的x和y比例使用“垃圾”数据进行绘图,然后更新使用bin数据创建的表面对象的zdata(修改为正确的格式)。
对bin数据的这种修改非常简单,包括重新整形为矩阵,然后复制并填充所有元素,该方法包含在下面的代码中。

根据问题末尾的ans变量,假设

  • ans(:,1)给出x值
  • ans(:,2)给出y值
  • ans(:,3)给出标准化的箱数

%// Inputs
zdata=ans(:,3);  %// zdata=rand(21*21,1); % for testing
xvalues = 0:0.05:1; 
yvalues = 0:0.05:1;

%// plot with junk data, [0,0] in this case
nx = numel(xvalues); ny = numel(yvalues);    
bincenters = { xvalues , yvalues };
hist3([0,0],bincenters);
Hsurface = get(gca,'children');

%// apply bin count format
pad = [0 0 0 0 0;0 1 1 0 0;0 1 1 0 0;0 0 0 0 0;0 0 0 0 0]; %// padding for each point
ztrans=kron(reshape(zdata,[nx,ny]),pad); %// apply padding to each point

%// update plot
set(Hsurface,'ZData',ztrans)

%// to set colour based on bar height
colormap('autumn');
set(Hsurface,'CData',ztrans,'FaceColor','interp')

输出

enter image description here