假设我有一个带有一些值的矩阵Z
,我希望通过以Z
高度绘制值来说明它。我想到的第一个解决方案是表面,但使用surf
和类似的函数与小矩阵看起来并不好。
所以我想到使用bar3
这样的3D条形图。但问题是这个功能总是按组而不是按高度设置颜色,我不能这样做。
以下是一个例子:
Z = peaks(5);
subplot 121
surf(Z)
title('Surface look bad')
subplot 122
bar3(Z)
title('The color is not by height')
我试图在bar3
返回的句柄中查找颜色属性(例如CData
和FaceColor
)但是丢失了所有值以及它们与条形本身的关系
最终,我希望有一个通用的解决方案,对于2个矩阵Z
和C
,我可以创建一个3D条形图,其高度由Z
给出,并由C
。
我该怎么办?
答案 0 :(得分:4)
函数bar3
返回一个 surface 对象,每个对应一个(即每种颜色一个),因此一组中的所有条形图基本上都被绘制为一个“破碎”曲面。这在this answer中解释得非常好,所以我在此不再重复。
相反,我会针对这个特定问题找到解决方案。表面的相关属性为CData
。当我们创建条形图时,每个曲面的CData
都会被赋予一个大小相同的矩阵(我们将得到它),它们都等于一个值。每个表面的值不同。这就是图形整体将其颜色图转换为组颜色的方式。
如上所述(并在linked answer中详细说明),每个组由一个曲面表示,因此需要一个完整的矩阵来定义曲面每个点的颜色。我们要做的第一件事是获得这个矩阵大小:
Z = peaks(5);
bar_h = bar3(Z);
% we take only the first one, but they are all the same size:
cdata_sz = size(bar_h(1).CData)
cdata_sz =
30 4
CData
始终有4列(请参阅here why),行数始终为6 *组数。这是因为它需要5个顶点来创建一个带有区域对象的闭合矩形(最后一个顶点就像第一个顶点),一条线用于带有NaN的条形之间的间距,因此它们看起来是分开的。
接下来,我们需要以正确的方式放大原始色彩图(大小与Z
相同)以适合CData
。基本上,我们只想为属于同一个条的所有顶点重复相同的值。假设Z
也是我们的颜色数据(即我们按高度颜色),我们会这样做:
z_color = repelem(Z,6,4)
现在我们需要将z_color
拆分为我们组中不同的单元格。每个单元格将包含一个表面对象的着色数据:
z_color = mat2cell(z_color,cdata_sz(1),ones(1,size(Z,2))*cdata_sz(2));
最后,我们将新的颜色数据应用于条形图:
set(bar_h,{'CData'},z_color.')
作为奖励,如果我们想从我们的栏中删除所有零值,可以通过将它们设置为NaN来轻松完成:
Z(abs(Z)<eps) = nan;
C(isnan(Z)) = nan; % if we use a colormap C different from Z
以上所有内容都可以归结为这个方便的功能:
function bar_h = Cbar3(Z,C,b,y)
% Z - The data
% C - CData (if other then Z values)
% b - Minimum absolute value to keep colored
% y - y-axis values to order the data by
if nargin<2, C = Z; end
if nargin<3 || isempty(b), b = 0; end
Z(abs(Z)<b) = nan;
C(isnan(Z)) = nan;
if nargin<4
bar_h = bar3(Z);
else
bar_h = bar3(y,Z);
end
cdata_sz = size(bar_h(1).CData);
z_color = repelem(C,6,4);
z_color = mat2cell(z_color,...
cdata_sz(1),ones(1,size(Z,2))*cdata_sz(2));
set(bar_h,{'CData'},z_color.')
end
使用示例:
subplot 121
Z = peaks(30);
Cbar3(Z,Z,0.5);
pbaspect auto
shading flat % just to get a cleaner look
title('Cbar3 using height as color')
subplot 122
Cbar3(Z,rand(size(Z)),0.5);
pbaspect auto
shading flat % just to get a cleaner look
title('Cbar3 using random as color')
结果:
答案 1 :(得分:2)
这是部分答案。
使用条形高度作为颜色的情况由官方MATLAB documentation涵盖。基本上,示例代码归结为:
function q45423394
hB = bar3(peaks(25)); colorbar;
for indE = 1:numel(hB)
hB(indE).CData = hB(indE).ZData;
end
之后您需要做的就是确保colormap
是您想要的。
答案 2 :(得分:0)