Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Customizing histogram plots

January 17, 2018 2 Comments

Earlier today, I was given the task of displaying a histogram plot of a list of values. In today’s post, I will walk through a few customizations that can be done to bar plots and histograms in order to achieve the desired results.
We start by binning the raw data into pre-selected bins. This can easily be done using the builtin histc (deprecated) or histcounts functions. We can then use the bar function to plot the results:

[binCounts, binEdges] = histcounts(data);
hBars = bar(hAxes, binEdges(1:end-1), binCounts);

[binCounts, binEdges] = histcounts(data); hBars = bar(hAxes, binEdges(1:end-1), binCounts);

Basic histogram bar plot
Basic histogram bar plot

Let’s improve the appearance: In my specific case, the data was financial return (percentage) values, so let’s modify the x-label format accordingly and display a title. To make the labels and title more legible, we decrease the axes FontSize to 8 and remove the axes box:

hAxes = hBar.Parent;
xtickformat(hAxes, '%g%%');
title(hAxes, 'Distribution of total returns (monthly %)');
set(hAxes, 'FontSize',8, 'Box','off')

hAxes = hBar.Parent; xtickformat(hAxes, '%g%%'); title(hAxes, 'Distribution of total returns (monthly %)'); set(hAxes, 'FontSize',8, 'Box','off')

Improved histogram bar plot
Improved histogram bar plot

So far nothing undocumented. Note that the xtickformat/ytickformat functions were only introduced in R2016b – for earlier Matlab releases see this post (which does rely on undocumented aspects).
Now, let’s use a couple of undocumented properties: to remove the excess white-space margin around the axes we’ll set the axes’ LooseInset property, and to remove the annoying white space between the tick labels and the X-axis we’ll set the XRuler‘s TickLabelGapOffset property to -2 (default: +2):

set(hAxes, 'LooseInset',[0,0,0,0]);    % default = [.13,.11,.095,.075]
hAxes.XRuler.TickLabelGapOffset = -2;  % default = +2

set(hAxes, 'LooseInset',[0,0,0,0]); % default = [.13,.11,.095,.075] hAxes.XRuler.TickLabelGapOffset = -2; % default = +2

Even better histogram bar plot
Even better histogram bar plot

Note that I used the undocumented axes XRuler property instead of the axes’ documented XAxis property, because XAxis is only available since R2015b, whereas XRuler (which points to the exact same object as XAxis) exists ever since R2014b, and so is better from a backward-compatibility standpoint. In either case, the ruler’s TickLabelGapOffset property is undocumented. Note that the ruler also contains another associated and undocumented TickLabelGapMultiplier property (default: 0.2), which I have not modified in this case.
Now let’s take a look at the bin labels: The problem with the bar plot above is that it’s not intuitively clear whether the bin for “5%”, for example, includes data between 4.5-5.5 or between 5.0-6.0 (which is the correct answer). It would be nicer if the labels were matched to the actual bin edges. There are 3 basic ways to fix this:

  1. We could modify the bar plot axes tick values and labels, in essence “cheating” by moving the tick labels half a bin leftward of their tick values (don’t forget to add the extra tick label on the right):
    hAxes.XTick(end+1) = hAxes.XTick(end) + 1;  % extra tick label on the right
    labels = hAxes.XTickLabels;       % preserve tick labels for later use below
    hAxes.XTick = hAxes.XTick - 0.5;  % move tick labels 1/2 bin leftward
    hAxes.XTickLabel = labels;        % restore pre-saved tick labels
    hAxes.XLim = hAxes.XLim - 0.5;    % ...and align the XLim

    hAxes.XTick(end+1) = hAxes.XTick(end) + 1; % extra tick label on the right labels = hAxes.XTickLabels; % preserve tick labels for later use below hAxes.XTick = hAxes.XTick - 0.5; % move tick labels 1/2 bin leftward hAxes.XTickLabel = labels; % restore pre-saved tick labels hAxes.XLim = hAxes.XLim - 0.5; % ...and align the XLim

    Improved labels
    Improved labels
  2. We could use the bar function’s optional 'histc' flag, in order to display the bars in histogram mode. The problem in histogram mode is that while the labels are now placed correctly, the bars touch each other – I personally find distinct bars that are separated by a small gap easier to understand.
    hBars = bar(..., 'histc');
    % [snip] - same customizations to hAxes as done above

    hBars = bar(..., 'histc'); % [snip] - same customizations to hAxes as done above

    Basic histogram plot
    Basic histogram plot

    With the original bar chart we could use the built-in BarWidth to set the bar/gap width (default: 0.8 meaning a 10% gap on either side of the bar). Unfortunately, calling bar with 'hist' or 'histc' (i.e. histogram mode) results in a Patch (not Bar) object, and patches do not have a BarWidth property. However, we can modify the resulting patch vertices in order to achieve the same effect:

    % Modify the patch vertices (5 vertices per bar, row-based)
    hBars.Vertices(:,1) = hBars.Vertices(:,1) + 0.1;
    hBars.Vertices(4:5:end,1) = hBars.Vertices(4:5:end,1) - 0.2;
    hBars.Vertices(5:5:end,1) = hBars.Vertices(5:5:end,1) - 0.2;
    % Align the bars & labels at the center of the axes
    hAxes.XLim = hAxes.XLim + 0.5;

    % Modify the patch vertices (5 vertices per bar, row-based) hBars.Vertices(:,1) = hBars.Vertices(:,1) + 0.1; hBars.Vertices(4:5:end,1) = hBars.Vertices(4:5:end,1) - 0.2; hBars.Vertices(5:5:end,1) = hBars.Vertices(5:5:end,1) - 0.2; % Align the bars & labels at the center of the axes hAxes.XLim = hAxes.XLim + 0.5;

    This now looks the same as option #1 above, except that the top-level handle is a Patch (not Bar) object. For various additional customizations, either Patch or Bar might be preferable, so you have a choice.

    Improved histogram plot
    Improved histogram plot
  3. Lastly, we could have used the builtin histogram function instead of bar. This function also displays a plot with touching bars, as above, using Quadrilateral objects (a close relative of Patch). The solution here is very similar to option #2 above, but we need to dig a bit harder to modify the patch faces, since their vertices is not exposed as a public property of the Histogram object. To modify the vertices, we first get the private Face property (explanation), and then modify its vertices, keeping in mind that in this specific case the bars have 4 vertices per bar and a different vertices matrix orientation:
    hBars = histogram(data, 'FaceAlpha',1.0, 'EdgeColor','none');
    % [snip] - same customizations to hAxes as done above
    % Get access to *ALL* the object's properties
    oldWarn = warning('off','MATLAB:structOnObject');
    warning off MATLAB:hg:EraseModeIgnored
    hBarsStruct = struct(hBars);
    warning(oldWarn);
    % Modify the patch vertices (4 vertices per bar, column-based)
    drawnow;  % this is important, won't work without this!
    hFace = hBarsStruct.Face;  % a Quadrilateral object (matlab.graphics.primitive.world.Quadrilateral)
    hFace.VertexData(1,:) = hFace.VertexData(1,:) + 0.1;
    hFace.VertexData(1,3:4:end) = hFace.VertexData(1,3:4:end) - 0.2;
    hFace.VertexData(1,4:4:end) = hFace.VertexData(1,4:4:end) - 0.2;

    hBars = histogram(data, 'FaceAlpha',1.0, 'EdgeColor','none'); % [snip] - same customizations to hAxes as done above % Get access to *ALL* the object's properties oldWarn = warning('off','MATLAB:structOnObject'); warning off MATLAB:hg:EraseModeIgnored hBarsStruct = struct(hBars); warning(oldWarn); % Modify the patch vertices (4 vertices per bar, column-based) drawnow; % this is important, won't work without this! hFace = hBarsStruct.Face; % a Quadrilateral object (matlab.graphics.primitive.world.Quadrilateral) hFace.VertexData(1,:) = hFace.VertexData(1,:) + 0.1; hFace.VertexData(1,3:4:end) = hFace.VertexData(1,3:4:end) - 0.2; hFace.VertexData(1,4:4:end) = hFace.VertexData(1,4:4:end) - 0.2;

In conclusion, there are many different ways to improve the appearance of charts in Matlab. Even if at first glance it may seem that some visualization function does not have the requested customization property or feature, a little digging will often find either a relevant undocumented property, or an internal object whose properties could be modified. If you need assistance with customizing your charts for improved functionality and appearance, then consider contacting me for a consulting session.

Related posts:

  1. Customizing contour plots – Contour labels, lines and fill patches can easily be customized in Matlab HG2. ...
  2. Customizing contour plots part 2 – Matlab contour labels' color and font can easily be customized. ...
  3. Customizing contour plots part 2 – The contour lines of 3D Matlab plot can be customized in many different ways. This is the 2nd article on this issue. ...
  4. Customizing axes tick labels – Multiple customizations can be applied to tick labels. ...
  5. Customizing axes part 3 – Backdrop – Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
  6. Customizing axes part 4 – additional properties – Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
Handle graphics HG2 Pure Matlab
Print Print
« Previous
Next »
2 Responses
  1. chengji chen February 13, 2023 at 04:45 Reply

    Hi, I have tried the method, but it didn’t work.

    I plot figure by m_map toolbox, the xticklabel will add to the yticklabel at the left-down corner, so I want to move down the xticklabel, but it didn’t work.

    Is there any other way to do it?

    • Yair Altman February 13, 2023 at 11:04 Reply

      m_map is a mapping tool, not even created by MathWorks and not part of the basic Matlab system. I have no idea why you think that the customizations to the builtin bar function in this article should also apply to m_map.
      If you need assistance with m_map, contact its developer (https://www.eoas.ubc.ca/~rich/map.html)

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top