【问题标题】:Bar plot x-axis Matlab条形图 x 轴 Matlab
【发布时间】:2018-12-30 14:11:52
【问题描述】:

我被 Matlab 中的条形图困住了。我让它在 Matlab 帮助和这个论坛上工作,直到这里,但在 x 轴上,仍然只有 2 个名称。我想在栏下有“名称”和现在显示 2 个名称的“类别”。谢谢!

values = [4 10...
    11 2 3;...
    4 1...
    5 2 -10];
names = {'PreSplitTotalEON' 'PostSplitTotalEON'...
    'PreSplitPureEON' 'PostSplitPureEON' 'PostSplitUniper';...
    'PreSplitTotalRWE' 'PostSplitTotalRWE'...
    'PreSplitPureRWE' 'PostSplitPureRWE' 'PostSplitInnogy'};
categories = {'EON', 'RWE'};
b = bar(values,'FaceColor','flat');
xticklabels([names(1,:)';names(2,:)'])         
% This will set labels to be used for each tick of the x-axis
xticks(1:1:length([names(1,:)';names(2,:)']))
% This will set how many ticks you want on the x-axis. Here, there
% should be 48 ticks being generated. One for each piece of data you have.
xtickangle(90)
% This will rotate the label so that the labels will not overlap
% with one another. This is in degrees.
for k = 1:size(values,2) % for fancier colors.
    b(k).CData = k;
end

【问题讨论】:

    标签: matlab plot matlab-figure


    【解决方案1】:

    默认方式是使用legend 来显示组中每个元素的名称。但是可以通过XOffsetXData 属性访问每个条的位置。请参阅 matlab 中心中的 this answer

    所以你可以使用类似的东西:

    ticksList = b(1).XData+arrayfun(@(x)x.XOffset, b)';
    xticks(ticksList(:))
    xticklabels([names(1,:)';names(2,:)'])
    

    正确显示每个栏下方的名称。但是,我看不到您希望如何在不重叠的情况下将每个条的名称和类别一起显示在条下方。您可以改为通过创建新轴来在顶部显示类别。添加类似的东西:

    ax1 = gca;
    ax2 = axes('Position', get(ax1, 'Position'),'Color', 'none');
    set(ax2, 'XAxisLocation', 'top','YAxisLocation','Right');
    set(ax2, 'XLim', get(ax1, 'XLim'),'YLim', get(ax1, 'YLim'));
    xticks(b(1).XData)
    xticklabels(categories)
    

    即完整的代码现在是:

    clear all
    close all
    
    values = [4 1 11 2 3; 4 1 5 2 -10];
    names = {'Pre split total EON' 'Post split total EON'...
        'Pre split pure EON' 'Post split pure EON' 'Post split Uniper';...
        'Pre split total RWE' 'Post split total RWE'...
        'Pre split pure RWE' 'Post split pure RWE' 'PostSplitInnogy'};
    categories = {'EON','RWE'};
    figure;
    b = bar(values,'FaceColor','flat');
    ticksList = b(1).XData+arrayfun(@(x)x.XOffset, b)';
    xticks(ticksList(:))
    xticklabels([names(1,:)';names(2,:)'])
    xtickangle(90)
    ax1 = gca;
    ax2 = axes('Position', get(ax1, 'Position'),'Color', 'none');
    set(ax2, 'XAxisLocation', 'top','YAxisLocation','Right');
    set(ax2, 'XLim', get(ax1, 'XLim'),'YLim', get(ax1, 'YLim'));
    set(ax2, 'YTick', []);
    xticks(b(1).XData)
    xticklabels(categories)
    for k = 1:size(values,2) % for fancier colors.
        b(k).CData = k;
    end
    

    【讨论】:

    • 我喜欢以上类别的解决方案,非常好,谢谢!但是,现在右侧 y 轴存在问题。它与左侧 y 轴有些不同。我会建议使用您建议的完整代码对您的回复进行编辑,您可以尝试解决问题吗?谢谢。
    • 谢谢。但是,当我放大或缩小图形时,右手 y 轴的问题仍然存在......你知道我的意思吗?
    • 现在应该通过禁用第二个轴上的 YTick 来修复。另一种选择是使用链接轴,因此它们具有相同的范围。但是有时在缩放轴后使用链接轴可能不会完全匹配。另一种选择是只使用@EBH answer中的文本函数
    【解决方案2】:
    • 您需要从图中观察 x 轴,并近似 条形的开始和结束 x 轴值。
    • 在检查中发现条形图从 0.54(间隙)开始 x 轴并在 2.32 附近结束。
    • 接下来,使用命令 xticks 将 x 轴分为 12 个刻度位置,
    • 然后使用命令 xticklabels 用所需的标签标记这些位置。就是这样。

    执行此操作所需的代码如下。

    close all
    clear all
    
    values = [4 10 ...
        11 2 3; ...
        4 1 ...
        5 2 -10];
    
    % just declare the names lables as a simple 1-D cell array
    % remove the columns and construct as row wise cell array
    names = {'PreSplitTotalEON','PostSplitTotalEON', ...
        'PreSplitPureEON', 'PostSplitPureEON', 'PostSplitUniper', ...
        'PreSplitTotalRWE', 'PostSplitTotalRWE', ...
        'PreSplitPureRWE', 'PostSplitPureRWE', 'PostSplitInnogy'};
    % declare the categories label
    categories = {'EON', 'RWE'};
    % construct the bar
    b = bar(values,'FaceColor','flat');
    
    %-> mark the respective xticks <-
    % on close inspepection, it was found that the bars starts
    % near 0.54 and end at nearly 2.31 at the x-axis
    % so divide the x axis in 12 ticks within those limits.
    xticks([linspace(0.54, 2.31, 12)]);
    
    % now put the lables at those limits, that all
    xticklabels({categories{1}, names{1:5}, categories{2}, names{6:10}})
    
    xtickangle(90)
    % This will rotate the label so that the labels will not overlap
    % with one another. This is in degrees.
    for k = 1:5 % for fancier colors.
        b(k).CData = k;
    end
    

    输出

    【讨论】:

      【解决方案3】:

      这里是您的代码获得所需输出的修复(内部解释):

      values = [4 10 11 2 3;
                4 1 5 2 -10];
      names = {'PreSplitTotal' 'PostSplitTotal'...
          'PreSplitPure' 'PostSplitPure' 'PostSplitUniper';...
          'PreSplitTotal' 'PostSplitTotal'...
          'PreSplitPure' 'PostSplitPure' 'PostSplitInnogy'}.'; % <-- note the transpose!
      categories = {'EON', 'RWE'};
      N_names = size(values,2);
      ax = axes('NextPlot','add'); % <-- same as 'hold on'
      col = lines(N_names); % choose your favorite colormap
      % draw the bars in pairs by their 'names':
      for k = 1:N_names % for fancier colors.categories
          b = bar(ax,[k k+N_names+1],values(:,k),0.15,...
              'FaceColor',col(k,:));
      end
      xticks([1:N_names (N_names+2:N_names*2+1)]) % does not crate a tick for the space between categories
      xticklabels(names(:))
      xtickangle(30)
      % place the category name on top of the axes:
      text(ceil(N_names/2)+[0 N_names+1],ax.YLim(2).*[1 1],categories,...
          'VerticalAlignment','bottom','HorizontalAlignment','center')
      

      【讨论】: