How to plot subset of X-axis names on bar plot?

Hello, I've run up against a problem that I can't seem to solve and need some help. Basically, I pull in 20 beer names (text strings) from an XLS, and want to create a bar plot of the first 10 of them. I can get it to plot the bars (plotData) for a subset, but every time, the bar plot contains all 20 beer names (plotNames), rather than the subset (10). I've even created a new array (plotNamesD), which contains only 10 beer name strings, but when I use 'bar' to plot it all 20 beer name strings are still plotted on the X-axis. Note that the reason that I loop through keywords is that I eventually want to apply this to other categories as well. Here is my example code:
clc
clear all
close all
rawData = {'Beer1','Draft Beer',NaN,NaN,NaN,928;...
'Beer2','Draft Beer',NaN,NaN,NaN,112;...
'Beer3','Draft Beer',NaN,NaN,NaN,55;...
'Beer4','Draft Beer',NaN,NaN,NaN,697;...
'Beer5','Draft Beer',NaN,NaN,NaN,256;...
'Beer6','Draft Beer',NaN,NaN,NaN,8;...
'Beer7','Draft Beer',NaN,NaN,NaN,430;...
'Beer8','Draft Beer',NaN,NaN,NaN,72;...
'Beer9','Draft Beer',NaN,NaN,NaN,76;...
'Beer10','Draft Beer',NaN,NaN,NaN,346;...
'Beer11','Draft Beer',NaN,NaN,NaN,86;...
'Beer12','Draft Beer',NaN,NaN,NaN,345;...
'Beer13','Draft Beer',NaN,NaN,NaN,4;...
'Beer14','Draft Beer',NaN,NaN,NaN,28;...
'Beer15','Draft Beer',NaN,NaN,NaN,98;...
'Beer16','Draft Beer',NaN,NaN,NaN,92;...
'Beer17','Draft Beer',NaN,NaN,NaN,94;...
'Beer18','Draft Beer',NaN,NaN,NaN,154;...
'Beer19','Draft Beer',NaN,NaN,NaN,367;...
'Beer20','Draft Beer',NaN,NaN,NaN,637};
% Determine number of rows
nRows = size( rawData, 1 );
% - Define category keywords
keywords = {'Appetizers',...
'Bottled Beer',...
'Draft Beer',...
'Lunch Specials',...
'Wine'} ;
% - Prealloc cell arrays for storing the output of find in column.
nKeyword = numel( keywords ) ;
keywordPos = cell( nRows, nKeyword ) ;
% - Iterate through elements of keywords and find in all data rows.
for kId = 1 : nKeyword
keywordPos(:,kId) = strfind( rawData(:,2), keywords{kId} ).' ;
end
% - Convert to arrays of logicals flagging "found at least one", which
% translates into "check not empty".
hasKeyword = ~cellfun( @isempty, keywordPos ) ;
numBeers = 10; % Number of top selling beers to plot
for kId = 1 : nKeyword
if strcmp(keywords{kId}, 'Draft Beer')
f=figure('WindowState','maximized');
plotData = cell2mat(rawData(hasKeyword(:,kId)==1,6));
% Sort from highest seller to lowest - may not be necessary
% bar(sort(plotData(:,1),'descend'));
plotNames = categorical(rawData(hasKeyword(:,kId)==1,1));
plotNames = reordercats(plotNames,rawData(hasKeyword(:,kId)==1,1));
% Attempt to reduce the size of the plotNames array to
% address why 'bar' can only plot the full array of names
plotNamesD = plotNames(1:numBeers);
plotDataD = plotData(1:numBeers);
bar(plotNamesD,plotDataD);
% Plot numbers at top of bar
text(1:length(plotData),plotData,num2str(plotData),'vert','bottom','horiz','center');
box off
% Plot categorgy name as the title of the plot
title(keywords(kId));
grid on;
end
end
And here is the current output:
I want to truncate this bar plot after "Beer10", but I'm struggling to do so even though the lengths of both plotDataD and plotNamesD is 10. As a side note, I also want to sort in descending order and make sure the beer names are correct and stay with their counts, but I haven't tackled that yet. Any help you can offer would be greatly appreciated!

 Accepted Answer

VBBV
VBBV on 12 Jan 2022
Edited: VBBV on 12 Jan 2022
plotNamesD = plotNames(1:kId);% use the for loop index
plotDataD = plotData(1:kId);
bar(plotNamesD,plotDataD);
hold on
Use the for loop index if you want to truncate the bar plot.

6 Comments

Hello, thanks for your response! Unfortunately, that solution won't work in the context of the nested for-if loop, because when 'keywords'=='Draft Beer', kId will always be 3. So simply changing the loop index to kId will only plot the first 3 beers, not the 10 (or other number) I wished to truncate at. Also, while this solution only plots the data for the first 3 beers, it still plots all 20 beer names as shown in the attached figure so its not truly "truncated":
Ok. Can you use the code outside of if-end. ? It seems that you are using inside if- end condition
I don't think so, because I want to loop through each of the product categories ('keywords'). If I used kId as my for loop index without the "if" condition, it creates bar plots for each product category, but only plots the 1st (kId==1), 2nd (kId==2), 3rd(kId==3) etc. row of sales data for each product category. Also, my original problem still stands - each of those bar plots shows the full list of product names along the X-axis, but the sales volume data is only plotted for the 1st, 2nd, 3rd, etc. entry.
clc
clear all
close all
rawData = {'Beer1','Draft Beer',NaN,NaN,NaN,928;...
'Beer2','Draft Beer',NaN,NaN,NaN,112;...
'Beer3','Draft Beer',NaN,NaN,NaN,55;...
'Beer4','Draft Beer',NaN,NaN,NaN,697;...
'Beer5','Draft Beer',NaN,NaN,NaN,256;...
'Beer6','Draft Beer',NaN,NaN,NaN,8;...
'Beer7','Draft Beer',NaN,NaN,NaN,430;...
'Beer8','Draft Beer',NaN,NaN,NaN,72;...
'Beer9','Draft Beer',NaN,NaN,NaN,76;...
'Beer10','Draft Beer',NaN,NaN,NaN,346;...
'Beer11','Draft Beer',NaN,NaN,NaN,86;...
'Beer12','Draft Beer',NaN,NaN,NaN,345;...
'Beer13','Draft Beer',NaN,NaN,NaN,4;...
'Beer14','Draft Beer',NaN,NaN,NaN,28;...
'Beer15','Draft Beer',NaN,NaN,NaN,98;...
'Beer16','Draft Beer',NaN,NaN,NaN,92;...
'Beer17','Draft Beer',NaN,NaN,NaN,94;...
'Beer18','Draft Beer',NaN,NaN,NaN,154;...
'Beer19','Draft Beer',NaN,NaN,NaN,367;...
'Beer20','Draft Beer',NaN,NaN,NaN,637};
% Determine number of rows
nRows = size( rawData, 1 );
% - Define category keywords
keywords = {'Appetizers',...
'Bottled Beer',...
'Draft Beer',...
'Lunch Specials',...
'Wine'} ;
% - Prealloc cell arrays for storing the output of find in column.
nKeyword = numel( keywords ) ;
keywordPos = cell( nRows, nKeyword ) ;
% - Iterate through elements of keywords and find in all data rows.
for kId = 1 : nKeyword
keywordPos(:,kId) = strfind( rawData(:,2), keywords{kId} ).' ;
end
% - Convert to arrays of logicals flagging "found at least one", which
% translates into "check not empty".
hasKeyword = ~cellfun( @isempty, keywordPos ) ;
numBeers = 10; % Number of top selling beers to plot
for kId = 1 : nKeyword
if strcmp(keywords{kId}, 'Draft Beer')
f=figure('WindowState','maximized');
plotData = cell2mat(rawData(hasKeyword(:,kId)==1,6));
% Sort from highest seller to lowest - may not be necessary
% bar(sort(plotData(:,1),'descend'));
plotNames = categorical(rawData(hasKeyword(:,kId)==1,1));
plotNames = reordercats(plotNames,rawData(hasKeyword(:,kId)==1,1));
% Attempt to reduce the size of the plotNames array to
% address why 'bar' can only plot the full array of names
plotNamesD = plotNames(1:numBeers);
plotDataD = plotData(1:numBeers);
bar(double(plotNamesD),plotDataD);% change from categorical to double
% Plot numbers at top of bar
%change this line too
text(1:length(plotDataD),plotDataD,num2str(plotDataD),'vert','bottom','horiz','center');
box off
% Plot categorgy name as the title of the plot
title(keywords(kId));
grid on;
end
end
change the text line. It seems you are using plotData instead of plotdataD
also change the categorical plotNamesD to double when you are using bar plot
Ok awesome! So you definitely caught at least one problem with my code (using plotData instead of plotDataD in the text line), so I'm going to mark this questions "solved" so that you get credit for it!
However, the second comment, changing the categorical plotNamesD to double doesn't meet my needs - in practice, there are like 500+ beer names, so I want the actual beer name (for example, the string 'Coors Light') to be displayed rather than just a number as in your example. So if I do not change the names to doubles, I still have the problem where all 20 beer names are plotted, rather than just the 10 I wanted. See below screenshot for an example:

Sign in to comment.

More Answers (0)

Categories

Find more on Environment and Settings in Help Center and File Exchange

Products

Release

R2020b

Asked:

on 11 Jan 2022

Commented:

on 14 Jan 2022

Community Treasure Hunt

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

Start Hunting!