使用分组的水平条形图绘制数组

时间:2016-05-16 13:44:03

标签: arrays matlab plot bar-chart

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

我的阵列是:

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'}

但它不起作用。

2 个答案:

答案 0 :(得分:1)

为什么你目前的方法不起作用

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

您可以在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函数和一组代表浮动条的线手动完成此操作。如果您想要考虑某种颜色协调的线条,请参考plot Array1 & Array2:[0;1;2;3;4;5;6;Nan;Nan;Nan;Nan;17;18;.....60]函数 - 我提供的代码(official documentation的修改版本)在红色和蓝色之间切换浮动条的颜色。我试图评论代码,以便清楚每个变量的目的。我在下面提供的代码与您想要绘制的浮动条形图匹配,如果您可以使用浮动在绘图上的2D线替换厚浮动条。

我使用您在问题中提供的数据来指定此脚本将输出的浮动水平条 - 屏幕截图显示在代码下方。 [6, 6, 43, 43],这些数组从0到6(长度= 6)和17到60(长度= 60 - 17 = 43)。因为有一个"不连续"从7到16的各种类型,我必须为每个数组定义两个浮动条。因此,我的长度数组中的前四个值是Array1。其中前6个和前43个对应Array2,第二个6和第二个43对应Array1。认识到这个"不连续",Array2x = 0的第一个浮动条的起点是Array1,{{1}的第二个浮动条的起点}和Array2x = 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)

输出:

this answer on StackOverflow

如何使用barh功能执行此操作?

简短的回答是您必须手动修改该功能。有人已经使用MATLAB bar3提供的条形图绘制函数之一完成了这项工作。如果您阅读barNew.m函数并稍微调整一下,可以重新应用此Resulting Floating Bar Graph中实现的逻辑。如果您想要指示从何处开始,我建议查看它们如何在绘图上指定其浮动条的z轴最小值和最大值,并应用相同的逻辑来指定x轴2D情况下浮动条的最小值和最大值。

我希望这有帮助,快乐编码! :)

答案 1 :(得分:0)

我在这里解释了生成这些类型图的方法。不确定它是否是最好的但它的工作原理并且无需手动执行任何操作。我根据以下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的图形上,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

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

enter image description here

现在我使用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) 

这将生成以下图表:

enter image description here