以不同方式为堆积条形图中的每个部分着色
Color each section in a stacked bar plot differently
我在下面有一个堆积条形图:-
这是使用以下方法生成的:
b = barh(1:3,rand(3,2),'stacked');
现在我有一个 3x2 单元格 C
每个单元格元素都是一个 1x3 RGB 数组。
C = cell(3,2);
for i = 1:3
for j = 1:2
C{i,j} = rand(1,3);
end
end
图中有6个方框,对应的颜色有6种。我想在框中填充这些指定的颜色。我想用这个方法:
b(1).Parent.Parent.Colormap = C;
...但是没有用。
有人可以建议如何绘制自定义堆叠条形图并能够控制每个条形段的颜色吗?我不认为调整 MATALB 的 bar
命令会有帮助。
您需要复制和操作 bar
(或 barh
)函数返回的图形对象
bar(y, 'stacked')
returns y
中每一列对应一个条形图对象。图形对象具有 XData
和 YData
字段,用于控制条形部分的位置和大小。由于同一列中的所有部分共享图形对象,因此您无法单独操作颜色。
例如,如果y
是一个2x3矩阵,bar
returns 3个图形对象。每个对象有:
XData
,包含条形索引的 1x2 向量
YData
,一个 1x2 向量,每个元素都是该部分的高度。
FaceColor
,所有这些部分共享的颜色
我的代码复制了这些图形对象,因此您有 6 个具有 1x1 XData
和 [=18 字段的图形对象,而不是具有 1x2 XData
和 YData
字段的 3 个图形对象=]字段,每个字段都有唯一的 FaceColor
.
从正常的 bar
或 barh
图表开始
figure;
n_bars = 2;
n_sections = 3;
%Initialize the bar graph with default coloring
b = bar(rand(n_bars, n_sections), 'stacked');
现在,制作一个新图形来保存具有操纵颜色的图
%Make new figure with new color scheme
f = figure;
a = axes('Parent', f);
%Colors
C = rand(6, 3);
对于原始图形对象,制作两个副本。
for jj = 1:n_sections
%Duplicate the bar graphics object results
section1 = copyobj(b(jj), a);
section2 = copyobj(b(jj), a);
% Remove one of the bars from each section
section1.YData(1) = 0;
section2.YData(2) = 0;
%Change the color
section1.FaceColor = C(sub2ind([n_bars, n_sections], 1, jj), :);
section2.FaceColor = C(sub2ind([n_bars, n_sections], 2, jj), :);
end
之前和之后!
想法是为每个数据行创建一个单独的图表,否则我们无法获得单个条形对象句柄。
ydata = rand(3,2); cdata={'r','g'; 'b','y';'c','k';'g','b'};
numplots = size(ydata,1);
h=zeros(numplots,2);
figure, hold on
for k=1:numplots,
h(k,:) = barh(nan(size(ydata)),'stacked');
set(h(k,1),'FaceColor',cdata{k,1});
set(h(k,2),'FaceColor',cdata{k,2});
tmp_ydata = get(h(k,1),'YData');
tmp_ydata(k) = ydata(k,1);
set(h(k,1),'YData',tmp_ydata);
tmp_ydata = get(h(k,2),'YData');
tmp_ydata(k) = ydata(k,2);
set(h(k,2),'YData',tmp_ydata);
end
hold off
详情请见post "Highlighting Parts of Charts"
Mike on MATLAB Graphics
根据 Cecilia 的回答,这是一个更通用的解决方案。
n_bars = 3;
n_sections = 4;
b = barh(rand(n_bars, n_sections), 'stacked');
f = figure;
a = axes('Parent', f);
C = rand(n_bars*n_sections, 3);
for jj = 1:n_sections
for ii=1:n_bars
section=copyobj(b(jj), a);
dummy=1:n_bars;
dummy(dummy==ii)=[];
section.YData(dummy) = 0;
section.FaceColor = C(sub2ind([n_bars, n_sections], ii, jj), :);
end
end
对于 n_bars
和 n_sections
的任何值,这都有效。如果有人可以建议矢量化或更有效的实施,请这样做。
我在下面有一个堆积条形图:-
这是使用以下方法生成的:
b = barh(1:3,rand(3,2),'stacked');
现在我有一个 3x2 单元格 C
每个单元格元素都是一个 1x3 RGB 数组。
C = cell(3,2);
for i = 1:3
for j = 1:2
C{i,j} = rand(1,3);
end
end
图中有6个方框,对应的颜色有6种。我想在框中填充这些指定的颜色。我想用这个方法:
b(1).Parent.Parent.Colormap = C;
...但是没有用。
有人可以建议如何绘制自定义堆叠条形图并能够控制每个条形段的颜色吗?我不认为调整 MATALB 的 bar
命令会有帮助。
您需要复制和操作 bar
(或 barh
)函数返回的图形对象
bar(y, 'stacked')
returns y
中每一列对应一个条形图对象。图形对象具有 XData
和 YData
字段,用于控制条形部分的位置和大小。由于同一列中的所有部分共享图形对象,因此您无法单独操作颜色。
例如,如果y
是一个2x3矩阵,bar
returns 3个图形对象。每个对象有:
XData
,包含条形索引的 1x2 向量YData
,一个 1x2 向量,每个元素都是该部分的高度。FaceColor
,所有这些部分共享的颜色
我的代码复制了这些图形对象,因此您有 6 个具有 1x1 XData
和 [=18 字段的图形对象,而不是具有 1x2 XData
和 YData
字段的 3 个图形对象=]字段,每个字段都有唯一的 FaceColor
.
从正常的 bar
或 barh
图表开始
figure;
n_bars = 2;
n_sections = 3;
%Initialize the bar graph with default coloring
b = bar(rand(n_bars, n_sections), 'stacked');
现在,制作一个新图形来保存具有操纵颜色的图
%Make new figure with new color scheme
f = figure;
a = axes('Parent', f);
%Colors
C = rand(6, 3);
对于原始图形对象,制作两个副本。
for jj = 1:n_sections
%Duplicate the bar graphics object results
section1 = copyobj(b(jj), a);
section2 = copyobj(b(jj), a);
% Remove one of the bars from each section
section1.YData(1) = 0;
section2.YData(2) = 0;
%Change the color
section1.FaceColor = C(sub2ind([n_bars, n_sections], 1, jj), :);
section2.FaceColor = C(sub2ind([n_bars, n_sections], 2, jj), :);
end
之前和之后!
想法是为每个数据行创建一个单独的图表,否则我们无法获得单个条形对象句柄。
ydata = rand(3,2); cdata={'r','g'; 'b','y';'c','k';'g','b'};
numplots = size(ydata,1);
h=zeros(numplots,2);
figure, hold on
for k=1:numplots,
h(k,:) = barh(nan(size(ydata)),'stacked');
set(h(k,1),'FaceColor',cdata{k,1});
set(h(k,2),'FaceColor',cdata{k,2});
tmp_ydata = get(h(k,1),'YData');
tmp_ydata(k) = ydata(k,1);
set(h(k,1),'YData',tmp_ydata);
tmp_ydata = get(h(k,2),'YData');
tmp_ydata(k) = ydata(k,2);
set(h(k,2),'YData',tmp_ydata);
end
hold off
详情请见post "Highlighting Parts of Charts" Mike on MATLAB Graphics
根据 Cecilia 的回答,这是一个更通用的解决方案。
n_bars = 3;
n_sections = 4;
b = barh(rand(n_bars, n_sections), 'stacked');
f = figure;
a = axes('Parent', f);
C = rand(n_bars*n_sections, 3);
for jj = 1:n_sections
for ii=1:n_bars
section=copyobj(b(jj), a);
dummy=1:n_bars;
dummy(dummy==ii)=[];
section.YData(dummy) = 0;
section.FaceColor = C(sub2ind([n_bars, n_sections], ii, jj), :);
end
end
对于 n_bars
和 n_sections
的任何值,这都有效。如果有人可以建议矢量化或更有效的实施,请这样做。