Is there a better way to plot categorical data radially than using the polarhistogram function?

6 views (last 30 days)
It is easy to plot categorical data with the histogram function:
authors = categorical({'Austen','Bradbury','Brown','Brown','Brown','Brown','Capote','Faulkner','Faulkner','Fitzgerald','Fitzgerald','Hawthorne','Heller','Hemingway','Hemingway','Hemingway','Irving','James','King','King','King','King','King','King','King','Lee','Lee','London','Melville','Miller','Miller','Morisson','O''Brien','Rand','Steinbeck','Steinbeck','Steinbeck','Twain','Twain','Twain','Twain','Twain','Updike','Updike','Updike','White'});
figure
histogram(authors,DisplayOrder='descend',Normalization='probability')
But, this does not work if you try to plot the data radially using polarhistogram, which requires that the data be numeric or logical. It is simple enough to get the number of counts for each cateogory in the categorical data by using the histcounts function, but plugging the numeric data directly into polarhistogram will not treat the numbers as discrete values. Instead, the function will automatically bin the data like this:
num_authors=histcounts(authors);
figure
polarhistogram(num_authors)
I have found a convoluted workaround in which you can specify the number of bins that you want the data to be divided into, but this is a pain because you have to define the widths of the bins in radians and the distance between tick marks in degrees:
% Get a list of all the category names
author_cats = categories(authors);
% Define number of bins
nbins = length(author_cats);
% Define widths of the bins (in radians)
binwidths = deg2rad(linspace(0,360,nbins+1));
% Define position of tick marks for adding categorical labels (in degrees)
center_bin_positions = (360/nbins) / 2;
bintickpositions = center_bin_positions : center_bin_positions *2 : 360 - center_bin_positions;
% Create plot
figure
h = polarhistogram('BinEdges',binwidths,'BinCounts',num_authors);
ax = gca;
% Normalize inner cicular tick marks as percentages
h.Normalization = 'percentage';
ax.RTickLabel = string(ax.RTickLabel) + '%';
% Adjust categorical tick label positions and add labels
thetaticks(bintickpositions)
thetaticklabels(author_cats)
for i = 1:nbins
value = sprintf('%0.1f',h.Values(i));
ax.ThetaTickLabel{i} = string(ax.ThetaTickLabel{i}) + ' (' + value + ' %)';
end
While this seems to work okay, making further customizations to the plot only makes things more complicated. For instance, I would prefer to plot the categorical data in descending order so that everything can be more easily compared.
Is there a better way to produce plots like this in MATLAB?
  2 Comments
Mario Malic
Mario Malic on 16 Jan 2024
What's wrong with histogram, you can adjust the looks of it, make bins wider and align text to be perpendicular to the X axis which should look just fine. Polar charts are a little bit complicated, maybe I would suggest to do it in Excel if you insist on that.
Austin M. Weber
Austin M. Weber on 16 Jan 2024
Edited: Austin M. Weber on 16 Jan 2024
The histogram function is great, but if your categorical data has a lot of categories it becomes almost impossible to read them on the x-axis. Radial (polar) histograms are a much better option for large categorical datasets. Here are a couple of great examples:

Sign in to comment.

Accepted Answer

Ravi
Ravi on 1 Feb 2024
Hi Austin M Weber,
Unfortunately, there is no direct option available in the “polarhistogram” function to arrange the bins in ascending or descending order. Instead, you can use the “radialhistogram” function provided in the attached file exchange link to plot the histogram in desired way.
Example on how to use the function:
  1. Download the file from the provided link and add the radialhistogram.m file to MATLAB path.
  2. Let us assume six programming languages “C”, “C++”, “Java”, “MATLAB”, “Python”, “C#” as categories.
  3. Let the count be the number of students using the languages in a class of 200 students.
  4. Please note that the “radialhistogram” function requires the data to be categorical.
% Generate a sample data
cat = categorical({'C', 'C++', 'Java', 'MATLAB', 'Python', 'C#'});
data = repelem(cat, [60, 15, 34, 45, 20, 26]);
tabulate(data);
Value Count Percent C 60 30.00% C# 26 13.00% C++ 15 7.50% Java 34 17.00% MATLAB 45 22.50% Python 20 10.00%
% To sort the data in descending order,
% specify 'descend' as the second argument.
radialhistogram(data, 'descend');
We can observe that the bins are in descending in anti-clockwise order.
Please refer to the following resource to learn more about radialhistogram function.
Hope this answer helps.
Thanks,
Ravi
  1 Comment
Austin M. Weber
Austin M. Weber on 1 Feb 2024
Edited: Austin M. Weber on 1 Feb 2024
@Ravi, the radialhistogram function is actually my own File Exchange submission. After I realized that there wasn't a simple way of making radial histograms in MATLAB I decided to go ahead and spend a few hours writing a function for it.
That said, I forgot to share the function on this MATLAB Answers forum, so thank you for doing it for me! I went ahead and accepted your answer.

Sign in to comment.

More Answers (0)

Products


Release

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!