You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
How to use boxchart and GroupByColor when having a matrix?
71 views (last 30 days)
Show older comments
Dear all,
I am trying to use a boxchart for plotting a (10000,10) matrix, where each column represents a single box.
In other words, I would like to plot a boxchart consisting of 10 boxes and 10,000 data points.
The problem is that all Answers in the forum I have read so far are related to vectors, not matrices. All my attempts of using boxchart have resulted in an error, which states that I cannot use a matrix but vectors. Transforming the matrix into a vector is not possible. Additionally, I would like to group the 10 columns in 3 categories by assigning each box the respective color:
column [1 2 3 4 5 6 7 8 9 10]
group [A A B C C B A B C A]
color: [r r g b b g r g b r ]
However, I cannot provide a vector with values and tell Matlab to group the columns of the matrix on the basis of a specific threshold (e.g. temperature), but I have to do this manually by paper and pencil and inform Matlab which column belongs to which group myself.
I use the following code:
figure (2)
groupname={'A','A','B','C','C','B','A','B','C','A'}';
boxchart(AX.t_k,'MarkerStyle', 'none','GroupByColor', groupname); % AX.t_k = (10000,10) matrix
And I get the following error:
Error using boxchart
'GroupByColor' parameter is not supported when the sample data argument is a matrix.
Could someone tell me, how I can use boxchart when using a matrix and how I can group each column with their respective color?
Thank you very much for your help!
Accepted Answer
Voss
on 15 Aug 2023
Maybe something like this:
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
colors = 'rgb';
colors = colors(findgroups(groupname));
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
boxchart(AX.t_k(:,ii),'MarkerStyle','none','BoxFaceColor',colors(ii),'XData',ii*ones(N,1))
end
ax = gca();
ax.XAxis.Categories = categorical(1:M);
23 Comments
Amelie
on 15 Aug 2023
Great, thank you very much, that was very helpful! It worked perfectly.
One more quick follow-up question for me to understand:
What is XData and ii*ones(N,1) for?
Thank you !
Voss
on 15 Aug 2023
Edited: Voss
on 15 Aug 2023
You're welcome!
ii*ones(N,1) is a 10000-by-1 column vector whose elements are all ii. As the loop iterates, ii goes from 1 to 10, so that's a column vector of 10000 1's the first time, then a column vector of 10000 2's the second time, and so on.
Including "'XData',ii*ones(N,1)" in the call to boxchart sets each respective boxchart's XData to the corresponding 10000-by-1 column vector. (XData has to be a vector the same size as the vector YData, which in this case is a column from your matrix, so that's why it's 10000-by-1.)
Setting the XData of each boxchart is necessary for the 10 different boxcharts to be located different x-locations (i.e., one boxchart at x = 1, one at x = 2, etc.). If you didn't specify that, they'd all be at x = 1 and overlapping.
Here's how it would look without specifying the XData:
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
colors = 'rgb';
colors = colors(findgroups(groupname));
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
boxchart(AX.t_k(:,ii),'MarkerStyle','none','BoxFaceColor',colors(ii))%,'XData',ii*ones(N,1))
end
ax = gca();
ax.XAxis.Categories = categorical(1:M);
Amelie
on 17 Aug 2023
Oh wow, thanks a lot for the detailed explanation ! It was very helpful, thank you !
Amelie
on 13 Sep 2023
I'm very sorry to bother you again but I have another question and cannot find the answer in this particular context in the forum.
Is it possible to reorder the boxchart by color? So that all green boxes are next to each other, red boxes are next to each other etc.
Unfortunately, the columns of the initial matrix are fixed and can't be adjusted.
Thank you very much for your help!
Voss
on 13 Sep 2023
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
colors = 'rgb';
[g,g_id] = findgroups(groupname);
order = [];
for ii = 1:numel(g_id)
order = [order find(g == ii)];
end
colors = colors(g(order));
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
boxchart(AX.t_k(:,order(ii)),'MarkerStyle','none','BoxFaceColor',colors(ii),'XData',ii*ones(N,1))
end
ax = gca();
ax.XAxis.Categories = categorical(order);
Amelie
on 14 Sep 2023
Great! It workes perfectly fine! Thank you very much for your help.
I forgot to ask: I would like to add a legend, i.e. so that in your example above the first 4 boxes in red are labeled "A" in the legend, the 3 green boxes are labeled "B" in the legend etc.
However, I failed up to now with any attempts, which are mostly based on
h1= boxchart(AX.t_k(:,1:4),'MarkerStyle','none','BoxFaceColor','r','XData',ii*ones(N,1));
h2= boxchart(AX.t_k(:,5:7),'MarkerStyle','none','BoxFaceColor','g','XData',ii*ones(N,1));
h3= boxchart(AX.t_k(:,7:10),'MarkerStyle','none','BoxFaceColor','b','XData',ii*ones(N,1));
legend([h1(1), h2(1) h2(1)], 'A', 'B', 'C');
But I haven't found another way in the forum how one can implement a legend that displayes collected groups.
If you have an idea, that would be great. But I don't want to bother you too much. You have helped me already a lot.
Voss
on 14 Sep 2023
Like this?
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
colors = 'rgb';
[g,g_id] = findgroups(groupname);
n_groups = numel(g_id);
order = [];
idx_for_legend = zeros(1,n_groups);
for ii = 1:n_groups
idx = find(g == ii);
order = [order idx];
idx_for_legend(ii) = idx(1);
end
colors = colors(g(order));
[N,M] = size(AX.t_k);
hold on
h = gobjects(1,M);
for ii = 1:M
h(order(ii)) = boxchart(AX.t_k(:,order(ii)),'MarkerStyle','none','BoxFaceColor',colors(ii),'XData',ii*ones(N,1));
end
legend(h(idx_for_legend),g_id)
ax = gca();
ax.XAxis.Categories = categorical(order);
Amelie
on 16 Sep 2023
Yes, that's perfect! Thank you very much, that is exactly what I was looking for !
Dan Houck
on 25 Oct 2023
How do you control the xticks and xticklabels? Say you want each group to have one tick mark and label. How would you do that?
Voss
on 25 Oct 2023
@Dan Houck: See below for how to do that in this example.
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
colors = 'rgb';
[g,g_id] = findgroups(groupname);
n_groups = numel(g_id);
order = [];
idx_for_legend = zeros(1,n_groups);
xticks = zeros(1,n_groups);
for ii = 1:n_groups
idx = find(g == ii);
order = [order idx];
idx_for_legend(ii) = idx(1);
xticks(ii) = idx((end+rem(numel(idx),2))/2);
end
colors = colors(g(order));
[N,M] = size(AX.t_k);
hold on
h = gobjects(1,M);
for ii = 1:M
h(order(ii)) = boxchart(AX.t_k(:,order(ii)),'MarkerStyle','none','BoxFaceColor',colors(ii),'XData',ii*ones(N,1));
end
legend(h(idx_for_legend),g_id)
ax = gca();
ax.XAxis.Categories = categorical(order);
ax.XTick = categorical(xticks);
ax.XTickLabels = g_id;
Voss
on 3 Apr 2024
@Amelie: Yes. Define an n_groups-by-3 matrix where each row is an RGB triplet; index that matrix by row when ordering the colors; use one row at a time when creating the boxcharts.
See below for an example.
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
% matrix of RGB triplets:
colors = [ ...
0 0.6 0; ...
0.6 0.6 0; ...
0.6 0 0.6; ...
];
% indexing by row:
colors = colors(findgroups(groupname),:);
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
% using one row of the colors matrix at a time:
boxchart(AX.t_k(:,ii),'MarkerStyle','none','BoxFaceColor',colors(ii,:),'XData',ii*ones(N,1))
end
ax = gca();
ax.XAxis.Categories = categorical(1:M);
Amelie
on 19 Apr 2024
I'm very sorry to bother you again but I have one follow-up question. Do you know if I can incorporate grids behind the boxcharts? If so, do you have an idea how to do it? The reason I ask is that I have problems to get the the grids in the background with 'Layer, 'bottom' or other commands suggested in the forum.
Many thanks !
Voss
on 19 Apr 2024
You should just be able to just use the grid function, as shown below:
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
% matrix of RGB triplets:
colors = [ ...
0 0.6 0; ...
0.6 0.6 0; ...
0.6 0 0.6; ...
];
% indexing by row:
colors = colors(findgroups(groupname),:);
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
% using one row of the colors matrix at a time:
boxchart(AX.t_k(:,ii),'MarkerStyle','none','BoxFaceColor',colors(ii,:),'XData',ii*ones(N,1))
end
ax = gca();
ax.XAxis.Categories = categorical(1:M);
grid(ax,'on')
Voss
on 19 Apr 2024
Oh, I see. I thought you wanted them to be visible through the boxchart.
To make the boxcharts obscure the grid lines, you'd have to increase the BoxFaceAlpha property of the boxcharts, which controls their opacity. Default BoxFaceAlpha for a boxchart is 0.2; here I'll change it to 1 to completely obscure whatever is behind it:
% generate some random data:
N = 10000;
M = 10;
AX = struct('t_k',zeros(N,M));
for ii = 1:M
AX.t_k(:,ii) = rand()*rand(N,1)+rand();
end
% plot 10 separate boxcharts, and color each one appropriately:
groupname = {'A','A','B','C','C','B','A','B','C','A'};
% matrix of RGB triplets:
colors = [ ...
0 0.6 0; ...
0.6 0.6 0; ...
0.6 0 0.6; ...
];
% indexing by row:
colors = colors(findgroups(groupname),:);
figure
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
% using one row of the colors matrix at a time:
boxchart(AX.t_k(:,ii), ...
'MarkerStyle','none', ...
'BoxFaceColor',colors(ii,:), ...
'XData',ii*ones(N,1), ...
'BoxFaceAlpha',1)
end
ax = gca();
ax.XAxis.Categories = categorical(1:M);
grid(ax,'on')
Unfortunately with that, as you can see, there's no longer a visual distinction between the box face and the box edge and median lines. To fix that, I'll make the BoxFaceColor lighter by changing the colors matrix, and keep the edge and median line colors as they were.
% matrix of RGB triplets:
colors = [ ...
0 1 0; ...
1 1 0; ...
1 0 1; ...
];
% indexing by row:
colors = colors(findgroups(groupname),:);
figure
[N,M] = size(AX.t_k);
hold on
for ii = 1:M
% using one row of the colors matrix at a time:
boxchart(AX.t_k(:,ii), ...
'MarkerStyle','none', ...
'BoxFaceColor',colors(ii,:), ...
'XData',ii*ones(N,1), ...
'BoxFaceAlpha',1, ...
'BoxEdgeColor',colors(ii,:)*0.6, ...
'BoxMedianLineColor',colors(ii,:)*0.6)
end
ax = gca();
ax.XAxis.Categories = categorical(1:M);
grid(ax,'on')
Amelie
on 20 Apr 2024
Thank you very much ! It's about time I sent you a fruit basket :)
Many thanks !
Voss
on 20 Apr 2024
You're welcome!
Hey, I'll take a fruit basket, sure. As long as the fruits are grouped by color.
More Answers (0)
See Also
Categories
Find more on Matrix Indexing 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!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)