【问题标题】:How to hide zero values in bar3 plot in MATLAB如何在MATLAB中的bar3图中隐藏零值
【发布时间】:2011-01-04 06:08:00
【问题描述】:

我有一个使用 bar3 plot 命令生成的二维直方图(图是 3D - 几个并排绘制的直方图)。但是,所有零值在 x-y 平面中都显示为平面正方形。有没有办法阻止 MATLAB 显示这些值?我已经尝试用 NaN 替换所有零,但它并没有改变情节的任何内容。这是我一直在试验的代码:

x1=normrnd(50,15,100,1); %generate random data to test code
x2=normrnd(40,13,100,1);
x3=normrnd(65,12,100,1);

low=min([x1;x2;x3]);
high=max([x1;x2;x3]);
y=linspace(low,high,(high-low)/4); %establish consistent bins for histogram
z1=hist(x1,y);
z2=hist(x2,y);
z3=hist(x3,y);
z=[z1;z2;z3]';
bar3(z)

如您所见,图中有很多零值。用 NaN 替换零后关闭图形并重新绘制似乎没有任何改变:

close
z(z==0)=NaN;
bar3(z)

【问题讨论】:

  • 您好,stem 也是如此,1D 也是如此,以防万一

标签: matlab plot data-visualization histogram


【解决方案1】:

一种解决方案是修改bar3 创建的图形对象。首先,您必须获取从bar3 返回的句柄:

h = bar3(z);

在您的情况下,h 将是一个 3 元素的句柄向量,每组彩色条对应一个。然后,以下代码应该使计数为零的 bin 不可见:

for i = 1:numel(h)
  index = logical(kron(z(:, i) == 0, ones(6, 1)));
  zData = get(h(i), 'ZData');
  zData(index, :) = nan;
  set(h(i), 'ZData', zData);
end

这是一个插图(带有强制性的手绘圆圈):

它是如何工作的......

如果您的 bin 计数向量为 N-by-1,则 bar3 将绘制 6*N 矩形块(即每个 bin 的 6 个长方体面)。因此h 中每组补丁对象的'ZData' 属性将为(6*N)-by-4,因为每个矩形面有4 个角。因此,'ZData' 属性的 6 行的每个集群是一个 bin 的 6 个面的一组 z 坐标。

上面的代码首先创建了一个逻辑向量,其中 bin 计数等于 0 的所有地方都是一个,然后使用 kron 函数将该向量的每个元素复制 6 次。这将成为 'ZData' 属性的行的索引,并且该索引用于将 z 坐标设置为 nan 用于空箱的补丁。这将导致补丁不被渲染。


编辑:

这里是一个稍微修改过的代码版本,它通过从绘制的条形的'ZData' property 获取条形高度使其更通用,因此它工作所需的只是从bar3 返回的句柄。我还将代码包装在一个函数中(没有错误和输入检查):

function remove_empty_bars(hBars)
  for iSeries = 1:numel(hBars)
    zData = get(hBars(iSeries), 'ZData');  % Get the z data
    index = logical(kron(zData(2:6:end, 2) == 0, ones(6, 1)));  % Find empty bars
    zData(index, :) = nan;                 % Set the z data for empty bars to nan
    set(hBars(iSeries), 'ZData', zData);   % Update the graphics objects
  end
end

【讨论】:

  • 在我提出问题后,我有了修改对象属性的想法,但我不知道从哪里开始。你的代码很好用——我把它放在一个 m 文件 bar3nonzero 中,现在我可以轻松地生成绘图了。
  • @gnovice: +1 ..你又一次找到了 kron 函数的好用处:)
  • 如果我可以建议,我会替换行 index = logical(kron(z(:,i) == 0,ones(6,1)));索引=逻辑(克朗(abs(z(:,i))
  • @Nicola:如果您正在处理任意浮点值,那是真的。然而,在这种情况下,OP 正在绘制直方图 bin 计数,它应该只包含精确的整数值。
【解决方案2】:

这是一个示例,说明如何隐藏零值条形图。我们从一个普通的BAR3 情节开始:

x = 1:7;
Y = jet(numel(x));
h = bar3(x,Y,'detached');
xlabel x; ylabel y; zlabel z; box on;

请注意,变量h 包含一个surface 句柄数组(在这种情况下为3 个,每个“组”条形图一个。这些组对应于Y 矩阵的列,每个都由一个不同的颜色)。

现在是隐藏零值的代码:

for i=1:numel(h)
    %# get the ZData matrix of the current group
    Z = get(h(i), '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(h(i), 'ZData',Z)
end

说明:

为每组柱形图创建一个surface 图形对象(句柄存储在h(i) 中)。它的 Z 坐标矩阵 ZData 表示为 6*N-by-4 矩阵(XDataYDataCData 矩阵相同),其中 N 是每组中矩形条的数量或 7上面的例子。

这样,每个矩形都用 6x4 矩阵表示(每个 X/Y/Z 坐标一个)。例如,这样一个矩形的坐标如下所示:

>> xx = get(h(3),'XData'); yy = get(h(3),'YData'); zz = get(h(3),'ZData');

>> xx(1:6,:)
ans =
          NaN          2.6          3.4          NaN
          2.6          2.6          3.4          3.4
          2.6          2.6          3.4          3.4
          NaN          2.6          3.4          NaN
          NaN          2.6          3.4          NaN
          NaN          NaN          NaN          NaN

>> yy(1:6,:)
ans =
          NaN          0.6          0.6          NaN
          0.6          0.6          0.6          0.6
          1.4          1.4          1.4          1.4
          NaN          1.4          1.4          NaN
          NaN          0.6          0.6          NaN
          NaN          NaN          NaN          NaN

>> zz(1:6,:)
ans =
          NaN            0            0          NaN
            0            1            1            0
            0            1            1            0
          NaN            0            0          NaN
          NaN            0            0          NaN
          NaN          NaN          NaN          NaN

每一列的第二列沿着左边的面追踪点,第三列沿着右边的面追踪点,当两者连接时将绘制矩形的4个面:

>> surface(xx(1:6,2:3), yy(1:6,2:3), zz(1:6,2:3), cc(1:6,2:3))
>> view(3)

第一列和最后一列将通过闭合矩形的边来绘制剩余的两个面。

所有这样的矩阵都连接为一个高矩阵,并且所有矩形都使用单个表面对象绘制。这是通过使用NaN 值来分隔不同部分来实现的,包括在同一矩形的点内和不同矩形之间。

因此,上述代码的作用是查找 Z 高度为零的矩形,并将其所有值替换为 NaN 值,这实际上告诉 MATLAB 不要绘制由这些点形成的曲面。

【讨论】:

    【解决方案3】:

    我的问题不是零值,而是 NaN 值(在 bar3 内转换为零值)。 我想继续显示值为 0 的元素,而不是值为 nan 的元素。 我稍微调整了一下代码,效果很好:

    for i = 1:numel(h)
      index = logical(kron(isnan(z(:,i)),ones(6,1)));
      zData = get(h(i),'ZData');
      zData(index,:) = nan;
      set(h(i),'ZData',zData);
    end
    

    谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-01
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 2017-12-28
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      相关资源
      最近更新 更多