【问题标题】:Plotting arrays using a grouped horizontal bar graph使用分组水平条形图绘制数组
【发布时间】:2016-05-16 13:44:03
【问题描述】:

我正在尝试生成一个类似于以下内容的图表:

我的数组是:

Array4:[Nan;Nan;.......;20;21;22;23;24;..........60]
Array3:[[Nan;Nan;.......;20;21;22;23;24;..........60]
Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
Array1:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]

我找不到正确的方法来对我的数组进行分组,以便按照上图所示的方式绘制它们。 我尝试使用以下功能解释:http://uk.mathworks.com/help/matlab/ref/barh.html

barh(1:numel(x),y,'hist') 

y=[Array1,Array2;Array3,Array4]x={'1m';'2m';'3m';......'60m'} 的位置

但它不起作用。

【问题讨论】:

  • 尝试设置 y = [Array1;Array2;Array3;Array4] 并提供 matlab 返回的任何错误。
  • @GameOfThrows。我尝试了 y=[Array1;Array2;Array3;Array4] 但我收到以下错误:“X 必须与 Y 长度相同”。
  • 表示数组 1 到 4 的长度需要相同,需要用 NaN 或 Zeros 填充,使它们的长度相同。
  • @GameOfThrows:所有数组的长度相同。它们都是 60x1 双数组。

标签: arrays matlab plot bar-chart


【解决方案1】:

为什么您当前的方法不起作用

您的直觉对我来说是有道理的,但是您使用的 barh 函数并不像您想象的那样工作。具体来说,您错误地解释了该函数的 xy 输入的含义。这些输入是常数值,而不是整个轴。第一个y 输入是指从x = 0 水平延伸的条的端点,第一个x 输入是指水平条在y 轴上的位置。为了说明我的意思,我提供了下面的水平条形图:

您可以在 MATLAB barh 函数的 official documentation 中找到相同的图片。用于生成此条形图的代码也在文档中给出,如下所示:

x = 1900:10:2000;
y = [57,91,105,123,131,150,...
 170,203,226.5,249,281.4];
figure;
barh(x, y);

x 数组的各个元素,相当令人困惑的是,在 y 轴上显示为每个条的起始位置。 y 数组的相应 元素是每个条的长度。这就是数组必须具有相同长度的原因,这说明它们不是 x 轴和 y 轴的规范,正如人们可能直观地认为的那样。

解决问题的方法

首先,最简单的方法是使用plot 函数和一组代表浮动条的线手动执行此操作。如果您想绘制带有某种颜色协调的线条,请咨询official documentation 以获取plot 函数 - 我提供的代码(this answer on StackOverflow 的修改版本)只是在之间切换浮动条的颜色红色和蓝色。我试图对代码进行注释,以便清楚每个变量的用途。我在下面提供的代码与您要绘制的浮动条形图相匹配,如果您可以将粗浮动条替换为浮动在绘图上的 2D 线。

我使用您在问题中提供的数据来指定此脚本将输出的浮动水平条 - 代码下方显示了屏幕截图。 Array1 & Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60],这些数组从 0 到 6(长度 = 6)和 17 到 60(长度 = 60 - 17 = 43)。因为从 7 到 16 存在某种“不连续性”,所以我必须为每个数组定义两个浮动条。因此,我的长度数组中的前四个值是[6, 6, 43, 43]。其中第一个6和第一个43对应Array1,第二个6和第二个43对应Array2。认识到这种“不连续性”,Array1Array2 的第一个浮动条的起点是 x = 0Array1Array2 的第二个浮动条的起点是 x = 7。综上所述,您将得到floating_bars 数组[0 0; 0 1.5; 17 0; 17 1.5] 中前四个点的 x 坐标。此数组中的 y 坐标仅用于区分 Array1Array2 等。

代码:

floating_bars=[0 0; 0 1.5; 17 0; 17 1.5; 20 6; 20 7.5]; % Each row is the [x,y] coordinate pair of the starting point for the floating bar
L=[6, 6, 43, 43, 40, 40]; % Length of each consecutive bar
thickness = 0.75;

figure;
    for i=1:size(floating_bars,1)
        curr_thickness = 0;
        % It is aesthetically pleasing to have thicker bars, this makes the plot look for like the grouped horizontal bar graph that you want
        while (curr_thickness < thickness)
            % Each bar group has two bars; set the first to be red, the second to be blue (i.e., even index means red bar, odd index means blue bar)
            if mod(i, 2)
                plot([floating_bars(i,1), floating_bars(i,1)+L(i)], [floating_bars(i,2) + curr_thickness, floating_bars(i,2) + curr_thickness], 'r')
            else
                plot([floating_bars(i,1), floating_bars(i,1)+L(i)], [floating_bars(i,2) + curr_thickness, floating_bars(i,2) + curr_thickness], 'b')
            end
        curr_thickness = curr_thickness + 0.05;
        hold on % Make sure that plotting the current floating bar does not overwrite previous float bars that have already been plotted
    end
end
ylim([ -10 30]) % Set the y-axis limits so that you can see more clearly the floating bars that would have rested right on the x-axis (y = 0)

输出:

我如何使用barh 函数做到这一点?

简短的回答是您必须手动修改函数。有人已经使用 MATLAB 提供的条形图绘图函数之一做到了这一点,bar3。如果您阅读他们的barNew.m 函数并对其进行一些调整,则可以将在此modified bar3 function 中实现的逻辑重新应用于您的目的。如果您想要一个关于从哪里开始的指针,我建议查看他们如何为绘图上的浮动条指定 z 轴最小值和最大值,并应用相同的逻辑来指定 x 轴最小值和最大值您的 2D 机箱中的浮动条。

我希望这会有所帮助,祝您编码愉快! :)

【讨论】:

  • 感谢您的解释。在您的第一种方法中,是否可以将这些浮动条成对分组,因为它出现在我发布的图表上?我可以用 2D 浮动线替换粗浮动条,但是,将它们成对分组对我来说非常重要。
  • 对不起,我刚刚意识到你已经这样做了(我想)。由于线条之间的空间很大,我没有意识到您已经尝试将它们分组。这是正确的吗?
  • @Sarah 我决定将每行与下一组行间隔 5 个单位。如果您愿意,您可以将我在 floating_bars 中指定的点的 y 坐标增量更改为较小的值,以用于配对的线,而对于不应该配对的线,将其保持较大。我将更新我提供的代码以反映我试图用文字解释的解决方案。
  • 我对答案的编辑对您有帮助吗?如果是这样,如果您接受我的回答,我将不胜感激。如果没有,你能解释一下你还有什么问题吗?谢谢!
  • 感谢您的解释,我已经理解您的示例,并且长期以来我一直在尝试弄清楚如何将您的示例与我的数据一起使用。但是,我不知道如何使用来自数组的数据而不是标准长度来计算每个连续柱的长度。
【解决方案2】:

我在这里解释了我生成这些类型的图表的方法。不确定它是否是最好的,但它可以工作,并且无需手动执行任何操作。我根据以下 Vladislav Martin 解释的事实提出了这个解决方案:“此数组中的 y 坐标仅用于区分 Array1、Array2 等”。

我原来的数组是:

Array4=[Nan....;20;21;22;23;24;..........60]
Array3=[Nan....;20;21;22;23;24;..........60]
Array2=[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]
Array1=[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]

x={'0m';'1m';'2m';'3m';'4m';....'60m'}

这些数组中包含的值参考图表上的 x 轴。为了使事情更简单并避免必须编写函数来确定数组中每个不连续点的长度,我将这些值替换为 y 轴位置值。基本上我给 Array1 y 轴位置值 0 和 Array2 0+0.02=0.02。对于 Array3,我给 y 轴位置值 0.5,给 Array4 0.5+0.02=0.52。这样,Array2 将绘制在靠近 Array1 的图形上,这将形成第一组,而 Array4 将绘制在靠近 Array3 的图形上,将形成第二组。

Datatable=table(Array1,Array2,Array3,Array4);

cont1=0;
cont2=0.02;

for col=1:2:size(Datatable,2)

   col2=col+1;   

   for row=1:size(Datatable,1)

      if isnan(Datatable{row,col})==0   % For first array in the group: If the value is not nan, I replace it for the corresponnding cont1 value
         Datatable{row,col}=cont1;
      end 

      if isnan(Datatable{row,col2})==0  % For second array in the group: If the value is not nan, I replace it for the corresponnding cont2 value
         Datatable{row,col2}=cont2;
      end  

   end

   cont1=cont1+0.5;

   cont2=cont2+0.5;

end

上述代码的结果将是如下表:

现在我使用 2D 浮动线绘制数组:

figure

for array=1:2:size(Datatable,2)

    FirstPair=cell2mat(table2cell(Datatable(:,array)));
    SecondPair=cell2mat(table2cell(Datatable(:,array+1)));

    hold on
    plot(1:numel(x),FirstPair,'r','Linewidth',6) 
    plot(1:numel(x),SecondPair,'b','Linewidth',6) 
    hold off

end

   set(gca,'xticklabel',x) 

这将生成以下图表:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2019-11-21
    • 2016-10-29
    • 1970-01-01
    相关资源
    最近更新 更多