R語言中有一個根據實值矩陣繪製色塊圖的程序(用於繪製相關係數矩陣圖),可以用豐富的顏色和形狀形象的展示矩陣元素值的大小。遺憾的是MATLAB中沒有這樣的函數,因此我就用MATLAB編寫了一個matrixplot函數,下面給出示例和源碼,與大家一起分享!
**********************************************
【例1】繪製網格線,網格中顯示矩陣元素。
顯示黑色文字:
>> x = [1,-0.2,0.3,0.8,-0.5
-0.2,1,0.6,-0.7,0.2
0.3,0.6,1,0.5,-0.3
0.8,-0.7,0.5,1,0.7
-0.5,0.2,-0.3,0.7,1];
>> XVarNames = {'xiezhh','heping','keda','tust','tianjin'};
>> matrixplot(x,'FillStyle','nofill','XVarNames',XVarNames,'YVarNames',XVarNames);
效果圖1:
根據矩陣元素值自動設置文字顏色:
>> matrixplot(x,'FillStyle','nofill','XVarNames',XVarNames,'YVarNames',XVarNames,'TextColor','Auto','ColorBar','on');
效果圖2:
【例2】繪製實值矩陣各元素對應的色塊,通過不同的“參數/參數值”控制色塊的形狀、大小、顏色等屬性。
方形色塊,充滿方格,灰白色字體
>> matrixplot(x,'XVarNames',XVarNames,'YVarNames',XVarNames,'TextColor',[0.6,0.6,0.6],'ColorBar','on');
效果圖3:
方形色塊,根據矩陣元素值自動確定色塊的大小和顏色,不顯示字體
>> matrixplot(x,'XVarNames',XVarNames,'YVarNames',XVarNames,'DisplayOpt','off','FigSize','Auto','ColorBar','on');
效果圖4:
橢圓形色塊,根據矩陣元素值自動確定色塊的大小和顏色,不顯示字體
>> matrixplot(x,'XVarNames',XVarNames,'YVarNames',XVarNames,'DisplayOpt','off','FigSize','Auto','ColorBar','on','FigShape','e');
效果圖5:
圓形色塊,根據矩陣元素值自動確定色塊的大小和顏色,不顯示字體,上三角形式顯示
>> matrixplot(x,'XVarNames',XVarNames,'YVarNames',XVarNames,'DisplayOpt','off','FigSize','Auto','ColorBar','on','FigShape','c','FigStyle','Triu');
效果圖6:
六邊形色塊,根據矩陣元素值自動確定色塊的大小和顏色,顯示字體,下三角形式顯示
>> matrixplot(x,'XVarNames',XVarNames,'YVarNames',XVarNames,'DisplayOpt','on','FigSize','Auto','ColorBar','on','FigShape','h','FigStyle','Tril');
效果圖7:
錶盤形色塊,根據矩陣元素值自動確定色塊的顏色,不顯示字體
>> matrixplot(x,'XVarNames',XVarNames,'YVarNames',XVarNames,'DisplayOpt','off','FigSize','Full','ColorBar','on','FigShape','d');
效果圖8:
【例3】讀取真彩圖片,繪製僞紅外圖。
>> I = double(imread('kids.tif'));
>> matrixplot(I,'DisplayOpt','off','colorbar','on','grid','off');
效果圖9:
最後貼上matrixplot函數的源碼,源碼中有詳細的調用格式及參數說明,感興趣的版友可以通過設置不同參數,做出更爲精彩的圖形,希望大家喜歡!
function matrixplot(data,varargin)
% 根據實值矩陣繪製色塊圖,用豐富的顏色和形狀形象的展示矩陣元素值的大小。
%
% matrixplot(data) 繪製矩陣色塊圖,data爲實值矩陣,每一個元素對應一個色塊,色
% 塊顏色由元素值大小決定。
%
% matrixplot(data, 'PARAM1',val1, 'PARAM2',val2, ...)
% 用成對出現的參數名/參數值控制色塊的各項屬性。可用的參數名/參數值如下:
% 'FigShape' --- 設定色塊的形狀,其參數值爲:
% 'Square' --- 方形(默認)
% 'Circle' --- 圓形
% 'Ellipse' --- 橢圓形
% 'Hexagon' --- 六邊形
% 'Dial' --- 錶盤形
%
% 'FigSize' --- 設定色塊的大小,其參數值爲:
% 'Full' --- 最大色塊(默認)
% 'Auto' --- 根據矩陣元素值自動確定色塊大小
%
% 'FigStyle' --- 設定矩陣圖樣式,其參數值爲:
% 'Auto' --- 矩形矩陣圖(默認)
% 'Tril' --- 下三角矩陣圖
% 'Triu' --- 上三角矩陣圖
%
% 'FillStyle' --- 設定色塊填充樣式,其參數值爲:
% 'Fill' --- 填充色塊內部(默認)
% 'NoFill' --- 不填充色塊內部
%
% 'DisplayOpt' --- 設定是否在色塊中顯示矩陣元素值,其參數值爲:
% 'On' --- 顯示矩陣元素值(默認)
% 'Off' --- 不顯示矩陣元素值
%
% 'TextColor' --- 設定文字的顏色,其參數值爲:
% 表示單色的字符('r','g','b','y','m','c','w','k'),默認爲黑色
% 1行3列的紅、綠、藍三元色灰度值向量([r,g,b])
% 'Auto' --- 根據矩陣元素值自動確定文字顏色
%
% 'XVarNames' --- 設定X軸方向需要顯示的變量名(默認爲X1,X2,...),其參數值爲:
% 字符串矩陣或字符串元胞數組,若爲字符串矩陣,其行數應與data的列數相同
% 若爲字符串元胞數組,其長度應與data的列數相同。
%
% 'YVarNames' --- 設定Y軸方向需要顯示的變量名(默認爲Y1,Y2,...),其參數值爲:
% 字符串矩陣或字符串元胞數組,若爲字符串矩陣,其行數應與data的行數相同
% 若爲字符串元胞數組,其長度應與data的行數相同。
%
% 'ColorBar' --- 設定是否顯示顏色條,其參數值爲:
% 'On' --- 顯示顏色條
% 'Off' --- 不顯示顏色條(默認)
%
% 'Grid' --- 設定是否顯示網格線,其參數值爲:
% 'On' --- 顯示網格線(默認)
% 'Off' --- 不顯示網格線
%
% Example:
% x = [1,-0.2,0.3,0.8,-0.5
% -0.2,1,0.6,-0.7,0.2
% 0.3,0.6,1,0.5,-0.3
% 0.8,-0.7,0.5,1,0.7
% -0.5,0.2,-0.3,0.7,1];
% matrixplot(x);
% matrixplot(x,'DisplayOpt','off');
% matrixplot(x,'FillStyle','nofill','TextColor','Auto');
% matrixplot(x,'TextColor',[0.7,0.7,0.7],'FigShap','s','FigSize','Auto','ColorBar','on');
% matrixplot(x,'TextColor','k','FigShap','d','FigSize','Full','ColorBar','on','FigStyle','Triu');
% XVarNames = {'xiezhh','heping','keda','tust','tianjin'};
% matrixplot(x,'FigShap','e','FigSize','Auto','ColorBar','on','XVarNames',XVarNames,'YVarNames',XVarNames);
%
% CopyRight:xiezhh(謝中華),2013.01.24編寫
% 對第一個輸入參數類型進行判斷
if ~ismatrix(data) || ~isreal(data)
error('輸入參數類型不匹配:第一個輸入參數應爲實值矩陣');
end
% 解析成對出現的參數名/參數值
[FigShape,FigSize,FigStyle,FillStyle,DisplayOpt,TextColor,XVarNames,...
YVarNames,ColorBar,GridOpt] = parseInputs(varargin{:});
% 產生網格數據
[m,n] = size(data);
[x,y] = meshgrid(0:n,0:m);
data = data(:);
maxdata = nanmax(data);
mindata = nanmin(data);
rangedata = maxdata - mindata;
if isnan(rangedata)
warning('MATLAB:warning1','請檢查您輸入的矩陣是否合適!');
return;
end
z = zeros(size(x))+0.2;
sx = x(1:end-1,1:end-1)+0.5;
sy = y(1:end-1,1:end-1)+0.5;
if strncmpi(FigStyle,'Tril',4)
z(triu(ones(size(z)),2)>0) = NaN;
sx(triu(ones(size(sx)),1)>0) = NaN;
elseif strncmpi(FigStyle,'Triu',4)
z(tril(ones(size(z)),-2)>0) = NaN;
sx(tril(ones(size(sx)),-1)>0) = NaN;
end
sx = sx(:);
sy = sy(:);
id = isnan(sx) | isnan(data);
sx(id) = [];
sy(id) = [];
data(id) = [];
if isempty(XVarNames)
XVarNames = strcat('X',cellstr(num2str((1:n)')));
else
if (iscell(XVarNames) && (numel(XVarNames) ~= n)) || (~iscell(XVarNames) && (size(XVarNames,1) ~= n))
error('X軸方向變量名應爲字符串矩陣或字符串元胞數組,其長度與輸入矩陣的列數相同');
end
end
if isempty(YVarNames)
YVarNames = strcat('Y',cellstr(num2str((1:m)')));
else
if (iscell(YVarNames) && (numel(YVarNames) ~= m)) || (~iscell(YVarNames) && (size(YVarNames,1) ~= m))
error('Y軸方向變量名應爲字符串矩陣或字符串元胞數組,其長度與輸入矩陣的行數相同');
end
end
% 繪圖
figure('color','w',...
'units','normalized',...
'pos',[0.289165,0.154948,0.409956,0.68099]);
axes('units','normalized','pos',[0.1,0.022,0.89,0.85]);
if strncmpi(GridOpt,'On',2)
mesh(x,y,z,...
'EdgeColor',[0.7,0.7,0.7],...
'FaceAlpha',0,...
'LineWidth',1); % 參考網格線
end
hold on;
axis equal;
axis([-0.1,n+0.1,-0.1,m+0.1,-0.5,0.5]);
view(2);
% 設置X軸和Y軸刻度位置及標籤
set(gca,'Xtick',(1:n)-0.5,...
'XtickLabel',XVarNames,...
'Ytick',(1:m)-0.5,...
'YtickLabel',YVarNames,...
'XAxisLocation','top',...
'YDir','reverse',...
'Xcolor',[0.7,0.7,0.7],...
'Ycolor',[0.7,0.7,0.7],...
'TickLength',[0,0]);
axis off
% 繪製填充色塊
if strncmpi(FillStyle,'Fill',3)
MyPatch(sx',sy',data',FigShape,FigSize);
end
% 顯示數值文本信息
if strncmpi(DisplayOpt,'On',2)
str = num2str(data,'%4.2f');
scale = 0.1*max(n/m,1)/(max(m,n)^0.55);
if strncmpi(TextColor,'Auto',3)
ColorMat = get(gcf,'ColorMap');
nc = size(ColorMat,1);
cid = fix(mapminmax(data',0,1)*nc)+1;
cid(cid<1) = 1;
cid(cid>nc) = nc;
TextColor = ColorMat(cid,:);
for i = 1:numel(data)
text(sx(i),sy(i),0.1,str(i,:),...
'FontUnits','normalized',...
'FontSize',scale,...
'fontweight','bold',...
'HorizontalAlignment','center',...
'Color',TextColor(i,:));
end
else
text(sx,sy,0.1*ones(size(sx)),str,...
'FontUnits','normalized',...
'FontSize',scale,...
'fontweight','bold',...
'HorizontalAlignment','center',...
'Color',TextColor);
end
end
% 設置X軸和Y軸刻度標籤的縮進方式
MyTickLabel(gca,FigStyle);
% 添加顏色條
if strncmpi(ColorBar,'On',2)
if any(strncmpi(FigStyle,{'Auto','Triu'},4))
colorbar('Location','EastOutside');
else
colorbar('Location','SouthOutside');
end
end
end
% ---------------------------------------------------
% 調整座標軸刻度標籤子函數
% ---------------------------------------------------
function MyTickLabel(ha,tag)
% 根據顯示範圍自動調整座標軸刻度標籤的函數
% ha 座標系句柄值
% tag 調整座標軸刻度標籤的標識字符串,可用取值如下:
% 'Auto' --- 將x軸刻度標籤旋轉90度,y軸刻度標籤不作調整
% 'Tril' --- 將x軸刻度標籤旋轉90度,並依次縮進,y軸刻度標籤不作調整
% 'Triu' --- 將x軸刻度標籤旋轉90度,y軸刻度標籤依次縮進
% Example:
% MyTickLabel(gca,'Tril');
%
% CopyRight:xiezhh(謝中華),2013.1編寫
if ~ishandle(ha)
warning('MATLAB:warning2','第一個輸入參數應爲座標系句柄');
return;
end
if ~strcmpi(get(ha,'type'),'axes')
warning('MATLAB:warning3','第一個輸入參數應爲座標系句柄');
return;
end
axes(ha);
xstr = get(ha,'XTickLabel');
xtick = get(ha,'XTick');
xl = xlim(ha);
ystr = get(ha,'YTickLabel');
ytick = get(ha,'YTick');
yl = ylim(ha);
set(ha,'XTickLabel',[],'YTickLabel',[]);
x = zeros(size(ytick)) + xl(1) - range(xl)/30;
y = zeros(size(xtick)) + yl(1) - range(yl)/70;
nx = numel(xtick);
ny = numel(ytick);
if strncmpi(tag,'Tril',4)
y = y + (1:nx) - 1;
elseif strncmpi(tag,'Triu',4)
x = x + (1:ny) - 1;
end
text(xtick,y,xstr,...
'rotation',90,...
'Interpreter','none',...
'color','r',...
'HorizontalAlignment','left');
text(x,ytick,ystr,...
'Interpreter','none',...
'color','r',...
'HorizontalAlignment','right');
end
% ---------------------------------------------------
% 根據散點數據繪製3維色塊圖子函數
% ---------------------------------------------------
function MyPatch(x,y,z,FigShape,FigSize)
% 根據散點數據繪製3維色塊圖
% MyPatch(x,y,z,FigShape,FigSize) x,y,z是實值數組,用來指定色塊中心點三維
% 座標。FigShape是字符串變量,用來指定色塊形狀。
% FigSize是字符串變量,用來指定色塊大小。
%
% CopyRight:xiezhh(謝中華), 2013.01 編寫
%
% Example:
% x = rand(10,1);
% y = rand(10,1);
% z = rand(10,1);
% MyPatch(x,y,z,'s','Auto');
%
% 輸入參數類型判斷
if nargin < 3
error('至少需要三個輸入參數');
end
if ~isreal(x) || ~isreal(y) || ~isreal(z)
error('前三個輸入應爲實值數組');
end
n = numel(z);
if numel(x) ~= n || numel(y) ~= n
error('座標應等長');
end
if strncmpi(FigSize,'Auto',3) && ~strncmpi(FigShape,'Ellipse',1)
id = (z == 0);
x(id) = [];
y(id) = [];
z(id) = [];
end
if isempty(z)
return;
end
% 求色塊頂點座標
rab1 = ones(size(z));
maxz = max(abs(z));
if maxz == 0
maxz = 1;
end
rab2 = abs(z)/maxz;
if strncmpi(FigShape,'Square',1)
% 方形
if strncmpi(FigSize,'Full',3)
r = rab1;
else
r = sqrt(rab2);
end
SquareVertices(x,y,z,r);
elseif strncmpi(FigShape,'Circle',1)
% 圓形
if strncmpi(FigSize,'Full',3)
r = 0.5*rab1;
else
r = 0.5*sqrt(rab2);
end
CircleVertices(x,y,z,r);
elseif strncmpi(FigShape,'Ellipse',1)
% 橢圓形
a = 0.48 + rab2*(0.57-0.48);
b = (1-rab2).*a;
EllipseVertices(x,y,z,a,b);
elseif strncmpi(FigShape,'Hexagon',1)
% 六邊形
if strncmpi(FigSize,'Full',3)
r = 0.5*rab1;
else
r = 0.5*sqrt(rab2);
end
HexagonVertices(x,y,z,r);
else
% 錶盤形
if strncmpi(FigSize,'Full',3)
r = 0.45*rab1;
else
r = 0.45*sqrt(rab2);
end
DialVertices(x,y,z,r);
end
end
%--------------------------------------------------
% 求色塊頂點座標並繪製色塊的子函數
%--------------------------------------------------
function SquareVertices(x,y,z,r)
% 方形
hx = r/2;
hy = hx;
Xp = [x-hx;x-hx;x+hx;x+hx;x-hx];
Yp = [y-hy;y+hy;y+hy;y-hy;y-hy];
Zp = repmat(z,[5,1]);
patch(Xp,Yp,Zp,'FaceColor','flat','EdgeColor','flat');
end
function CircleVertices(x,y,z,r)
% 圓形
t = linspace(0,2*pi,30)';
m = numel(t);
Xp = repmat(x,[m,1])+cos(t)*r;
Yp = repmat(y,[m,1])+sin(t)*r;
Zp = repmat(z,[m,1]);
patch(Xp,Yp,Zp,'FaceColor','flat','EdgeColor','flat');
end
function EllipseVertices(x,y,z,a,b)
% 橢圓形
t = linspace(0,2*pi,30)';
m = numel(t);
t0 = -sign(z)*pi/4;
t0 = repmat(t0,[m,1]);
x0 = cos(t)*a;
y0 = sin(t)*b;
Xp = repmat(x,[m,1]) + x0.*cos(t0) - y0.*sin(t0);
Yp = repmat(y,[m,1]) + x0.*sin(t0) + y0.*cos(t0);
Zp = repmat(z,[m,1]);
patch(Xp,Yp,Zp,'FaceColor','flat','EdgeColor','flat');
end
function HexagonVertices(x,y,z,r)
% 六邊形
t = linspace(0,2*pi,7)';
m = numel(t);
Xp = repmat(x,[m,1])+cos(t)*r;
Yp = repmat(y,[m,1])+sin(t)*r;
Zp = repmat(z,[m,1]);
patch(Xp,Yp,Zp,'FaceColor','flat','EdgeColor','flat');
end
function DialVertices(x,y,z,r)
% 錶盤形
% 繪製錶盤扇形
maxz = max(abs(z));
t0 = z*2*pi/maxz-pi/2;
t0 = cell2mat(arrayfun(@(x)linspace(-pi/2,x,30)',t0,'UniformOutput',0));
m = size(t0,1);
r0 = repmat(r,[m,1]);
Xp = [x;repmat(x,[m,1]) + r0.*cos(t0);x];
Yp = [y;repmat(y,[m,1]) + r0.*sin(t0);y];
Zp = repmat(z,[m+2,1]);
patch(Xp,Yp,Zp,'FaceColor','flat','EdgeColor',[0,0,0]);
% 繪製錶盤圓周
t = linspace(0,2*pi,30)';
m = numel(t);
Xp = repmat(x,[m,1])+cos(t)*r;
Yp = repmat(y,[m,1])+sin(t)*r;
Zp = repmat(z,[m,1]);
Xp = [Xp;flipud(Xp)];
Yp = [Yp;flipud(Yp)];
Zp = [Zp;flipud(Zp)];
patch(Xp,Yp,Zp,'FaceColor','flat','EdgeColor',[0,0,0]);
end
%--------------------------------------------------------------------------
% 解析輸入參數子函數1
%--------------------------------------------------------------------------
function [FigShape,FigSize,FigStyle,FillStyle,DisplayOpt,TextColor,...
XVarNames,YVarNames,ColorBar,GridOpt] = parseInputs(varargin)
if mod(nargin,2)~=0
error('輸入參數個數不對,應爲成對出現');
end
pnames = {'FigShape','FigSize','FigStyle','FillStyle','DisplayOpt',...
'TextColor','XVarNames','YVarNames','ColorBar','Grid'};
dflts = {'Square','Full','Auto','Fill','On','k','','','Off','On'};
[FigShape,FigSize,FigStyle,FillStyle,DisplayOpt,TextColor,XVarNames,...
YVarNames,ColorBar,GridOpt] = parseArgs(pnames, dflts, varargin{:});
validateattributes(FigShape,{'char'},{'nonempty'},mfilename,'FigShape');
validateattributes(FigSize,{'char'},{'nonempty'},mfilename,'FigSize');
validateattributes(FigStyle,{'char'},{'nonempty'},mfilename,'FigStyle');
validateattributes(FillStyle,{'char'},{'nonempty'},mfilename,'FillStyle');
validateattributes(DisplayOpt,{'char'},{'nonempty'},mfilename,'DisplayOpt');
validateattributes(TextColor,{'char','numeric'},{'nonempty'},mfilename,'TextColor');
validateattributes(XVarNames,{'char','cell'},{},mfilename,'XVarNames');
validateattributes(YVarNames,{'char','cell'},{},mfilename,'YVarNames');
validateattributes(ColorBar,{'char'},{'nonempty'},mfilename,'ColorBar');
validateattributes(GridOpt,{'char'},{'nonempty'},mfilename,'Grid');
if ~any(strncmpi(FigShape,{'Square','Circle','Ellipse','Hexagon','Dial'},1))
error('形狀參數只能爲Square, Circle, Ellipse, Hexagon, Dial 之一');
end
if ~any(strncmpi(FigSize,{'Full','Auto'},3))
error('圖形大小參數只能爲Full, Auto 之一');
end
if ~any(strncmpi(FigStyle,{'Auto','Tril','Triu'},4))
error('圖形樣式參數只能爲Auto, Tril, Triu 之一');
end
if ~any(strncmpi(FillStyle,{'Fill','NoFill'},3))
error('圖形填充樣式參數只能爲Fill, NoFill 之一');
end
if ~any(strncmpi(DisplayOpt,{'On','Off'},2))
error('顯示數值參數只能爲On,Off 之一');
end
if ~any(strncmpi(ColorBar,{'On','Off'},2))
error('顯示顏色條參數只能爲On,Off 之一');
end
if ~any(strncmpi(GridOpt,{'On','Off'},2))
error('顯示網格參數只能爲On,Off 之一');
end
end
%--------------------------------------------------------------------------
% 解析輸入參數子函數2
%--------------------------------------------------------------------------
function [varargout] = parseArgs(pnames,dflts,varargin)
% Copyright 2010-2011 The MathWorks, Inc.
% $Revision: 1.1.6.2 $ $Date: 2011/05/09 01:27:26 $
% Initialize some variables
nparams = length(pnames);
varargout = dflts;
setflag = false(1,nparams);
unrecog = {};
nargs = length(varargin);
dosetflag = nargout>nparams;
dounrecog = nargout>(nparams+1);
% Must have name/value pairs
if mod(nargs,2)~=0
m = message('stats:internal:parseArgs:WrongNumberArgs');
throwAsCaller(MException(m.Identifier, '%s', getString(m)));
end
% Process name/value pairs
for j=1:2:nargs
pname = varargin{j};
if ~ischar(pname)
m = message('stats:internal:parseArgs:IllegalParamName');
throwAsCaller(MException(m.Identifier, '%s', getString(m)));
end
mask = strncmpi(pname,pnames,length(pname)); % look for partial match
if ~any(mask)
if dounrecog
% if they've asked to get back unrecognized names/values, add this
% one to the list
unrecog((end+1):(end+2)) = {varargin{j} varargin{j+1}};
continue
else
% otherwise, it's an error
m = message('stats:internal:parseArgs:BadParamName',pname);
throwAsCaller(MException(m.Identifier, '%s', getString(m)));
end
elseif sum(mask)>1
mask = strcmpi(pname,pnames); % use exact match to resolve ambiguity
if sum(mask)~=1
m = message('stats:internal:parseArgs:AmbiguousParamName',pname);
throwAsCaller(MException(m.Identifier, '%s', getString(m)));
end
end
varargout{mask} = varargin{j+1};
setflag(mask) = true;
end
% Return extra stuff if requested
if dosetflag
varargout{nparams+1} = setflag;
if dounrecog
varargout{nparams+2} = unrecog;
end
end
end