gusucode.com > datatypes 工具箱matlab源码程序 > datatypes/@categorical/pie.m
function h = pie(varargin) %PIE Pie chart of a categorical array % PIE(X) draws a pie chart for categorical array X with category counts % normalized to total number of elements. <undefined> elements are ignored. % % PIE(X,EXPLODE) is used to specify slices that should be pulled out from % the pie. EXPLODE can be category names or a logical vector with the % same number of elements as categories in X. When EXPLODE is category % names, slices corresponding to categories specified will be pulled out. % When EXPLODE is a logical vector, slices corresponding to TRUE in % category order will be pulled out. % % PIE(X,EXPLODE,LABELS) is used to label each pie slice with LABELS. % LABELS must be a character vector or cell array of character vectors. % If LABELS is a cell array, it must have the same number of elements as % categories in X. % % PIE(AX,...) plots into AX instead of GCA. % % H = PIE(...) returns a vector containing patch and text handles. % % Example % -------- % Plot a pie chart from a categorical array % X = categorical({'North','South','North','East','South','West'}); % pie(X); % % Explode slices corresponding to categories 'North' and 'South' % pie(X, {'North','South'}); % % Explode categories 'North' and 'South' using logical vector % pie(X, [false true true false]); % % Copyright 2014-2016 The MathWorks, Inc. % Parse and process inputs [axesHandle, data, explode, labels] = pieProcessInputs(varargin); % Compute category counts and ignore categories with zero counts counts = countcats(data); categoryNames = categories(data); if any(counts==0) % some category has zero counts nnzCountsInd = find(counts); % categories with zero counts are ignored counts = counts(nnzCountsInd); explode = explode(nnzCountsInd); categoryNames = categoryNames(nnzCountsInd); if ~isempty(labels) labels = labels(nnzCountsInd); end end % Plot pie chart and label slices appropriately lh = pie(axesHandle, counts, explode); legend(categoryNames); legend('off'); pieInsertLabels(lh, labels, categoryNames, counts); if nargout>0, h=lh; end end %%%%%%%%%%%%%%%%%%%%%%%%% HELPER PIEPROCESSINPUTS %%%%%%%%%%%%%%%%%%%%%%%%% function [axesHandle, catData, explode, labels] = pieProcessInputs(arg) % Get axes handle for this plot if ishghandle(arg{1},'axes') axesHandle = arg{1}; % get user specified axes handle arg(1)=[]; % delete 1st argument so subsequent input parsing doesn't need to special case else axesHandle = []; end try catData = arg{1}; numParameters = numel(arg); switch numParameters case 1 explode = {}; labels = {}; case 2 explode = arg{2}; labels = {}; case 3 explode = arg{2}; labels = arg{3}; otherwise error(message('MATLAB:categorical:pie:TooManyInputs')); end catData = validateData(catData); explode = validateExplode(explode, catData); labels = validateLabels(labels, numel(categories(catData))); catch ME throwAsCaller(ME); end % Create new axes if user did not specify if isempty(axesHandle), axesHandle = gca; end end %%%%%%%%%%%%%%%%%%%%%%%%%%% HELPER VALIDATEDATA %%%%%%%%%%%%%%%%%%%%%%%%%%% function data = validateData(data) data = reshape(data,numel(data),1); if isempty(data) || all(isundefined(data)) error(message('MATLAB:categorical:pie:InvalidData')); end end %%%%%%%%%%%%%%%%%%%%%%%%% HELPER VALIDATEEXPLODE %%%%%%%%%%%%%%%%%%%%%%%%%% function explode = validateExplode(explode, catData) if isempty(explode) explode = false(size( countcats(catData) )); elseif islogical(explode) || (isnumeric(explode) && all(~isnan(explode))) if ~isequal( numel(explode), numel(categories(catData)) ) % length of EXPLODE must equal that of the categorical array error(message('MATLAB:categorical:pie:InvalidExplodeLogical')); end explode = logical(explode); elseif matlab.internal.datatypes.isCharStrings(explode) if ~all(iscategory(catData,explode)) % explode specified as category names error(message('MATLAB:categorical:pie:InvalidExplodeName')); end explode = ismember(categories(catData), explode); else error(message('MATLAB:categorical:pie:InvalidExplodeType')); end end %%%%%%%%%%%%%%%%%%%%%%%%%% HELPER VALIDATELABELS %%%%%%%%%%%%%%%%%%%%%%%%%% function labels = validateLabels(labels, numCat) if ~matlab.internal.datatypes.isCharStrings(labels,true) error(message('MATLAB:categorical:pie:InvalidLabel')); elseif ~isempty(labels) && ~isequal(numel(labels), numCat) % LABELS must be empty or have number of elements as that of categories error(message('MATLAB:categorical:pie:InvalidLabel')); end end %%%%%%%%%%%%%%%%%%%%%%%%% HELPER PIEINSERTLABELS %%%%%%%%%%%%%%%%%%%%%%%%%% function labels = pieInsertLabels(h, labels, catNames, catCounts) if isempty(labels) percentageStrings = num2str(round(100*nonzeros(catCounts)./sum(catCounts)), '(%d%%)'); labels = strcat(catNames, {' '}, percentageStrings); end % Save 'Extent' property of default labels for positioning of custom labels hText = findobj(h,'Type','text'); oldExtents = get(hText,'Extent'); if iscell(oldExtents), oldExtents = cell2mat(oldExtents); end % Set labels to categories and corresponding percentages labels = reshape(labels, size(hText)); set(hText,{'String'},labels); % Compute position of custom labels so they do not overlap with the slices newExtents = get(hText,'Extent'); if iscell(newExtents), newExtents = cell2mat(newExtents); end width_change = newExtents(:,3)-oldExtents(:,3); offset = sign(oldExtents(:,1)) .* (width_change/2); textPositions = get(hText,{'Position'}); if iscell(textPositions), textPositions = cell2mat(textPositions); end textPositions(:,1) = textPositions(:,1) + offset; % add offset adjustment % Set 'Position' property for each custom label for i=1:numel(hText) set(hText(i),'Position',textPositions(i,:)) end end