Identifying and keeping duplicates but with a suffix
Show older comments
Hello, I have a column vector that I use for x values for a Bar Chart from data extracted from a UITable.
Y=cell2mat(data(:,4))
X=data(:,2);
Xdata = categorical(X);
X = reordercats(Xdata,X);
b1=bar(X,Y,'Parent',app.UIAxes2);
My x data (Column vector) is one of 3 numbers 405, 532 or 660.
The data can be any of these and with any number of repeats e.g
405
405
405
405
405
or
405
532
532
660
405
The problem is the bar chart cannot handle repeat values. I'd still like to plot and thought one way would be to identify repeats and place an _ with a number, but am not sure how to
e.g
405
405
405
405
405
becomes
405_1
405_2
405_3
405_4
405_5
and
405
532
532
660
405
becomes
405_1
532_1
532_2
660
405_2
Thanks for any help
2 Comments
That sounds like a really bad idea...but I don't understand what you would want your plot to look like???
What would your ideal chart be if didn't have the limitation? Are multiple X of the same value really different Y or should you just not use sum(Y) conditional on X or similar?
With the data similar to what you've shown, it would seem there would be a very high number of X values that would make bar plot very crowded?
Knowing more of what data represent and what is purpose of plot could lead to better answers...
ADDENDUM:
I think what you want is to create a grouped plot on the unique(X) with the Y associated with each.
To do this, pass unique(X) as the x vector and create a yBar data array where each each unique x value is matched by a row that contains the y values associated with it. This would then be a 3xM array; M would be the maximum number of observations of a given x; the elements in the shorter rows of the array would be NaN which will be silently ignored by bar()
It would be more convenient if one could pass a cell array instead of only an ordinary array, but that would appear to be the way to solve your wants.
Jason
on 27 Aug 2020
Accepted Answer
More Answers (1)
OK, this isn't complete, but is probably the simplest way to build something to do what you'd like -- it would need to be refined and made into a function, but the general idea is pretty simple...using the same [x y] data had before in sorted order...
colors=reshape([hBar.FaceColor],3,[]).'; % save the default color map from previous for convenience
figure
hBar(1)=bar(1,Y(1)); % the first one at ordinal position 1
hold on % prepare to add on top existing bar
c=1; % initial color index value
j=1; % x position location for each bar
for i=2:size(X,1) % add rest to same plot
if X(i)~=X(i-1), j=j+0.5; end % if new wave number, put separation to simulate groups
c=c+1; % increment color for next group
j=j+1; % increment the ordinal number
hBar(i)=bar(j,Y(i),'FaceColor',colors(c,:)); % plot at adjusted ordinal position in group color
end
xticks([hBar.XEndPoints]) % put tick marks at middle each bar
xticklabels(categorical(X)) % label with the wave numbers
title('Simulated Grouped by Wave Number')
grid on
Now, one has a separate bar() object handle for each bar so can set color as desired...this just cycles through the (somewhat ugly) default sequence; you can define whatever color array you wish.
The biggest refinement I see missing here is not computing the midpoint of the groups for locating the tick marks so only have one label for the wave number group--I ran out of time altho don't think it's hard, one just needs a running sum of the XendPoints values for each group and compute the mean for that set when the group/wave number changes and save that value in array to use for xticks argument. Then you will use the unique categorical variable as labels instead of the full X array.
The above initial step gets to this point --

Well, OK, I lied... :) Couldn't stand it!!!

The modifications are --
N=groupcounts(x); % bring this back...
tk=zeros(size(N)); % accumlator for the tick position calculation
hBar(1)=bar(1,Y(1));
tk(1)=hBar(1).XEndPoints; % initial position (if choose to use something other than 1)
c=1;j=1;
for i=2:size(X,1)
if X(i)~=X(i-1)
j=j+0.5;
tk(c)=tk(c)/N(c); % calculate the group tick average for midpoint for last group
c=c+1;
end
j=j+1;h
Bar(i)=bar(j,Y(i),'FaceColor',colors(c,:));
tk(c)=tk(c)+hBar(i).XEndPoints; % accumulate running sum for working group
end
xticks(tk)
xticklabels(unique(X))
Categories
Find more on Axis Labels in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
