问题
I'm trying to visualize a soft clustering. There are a number of points and a small number of clusters, each point belongs to each cluster with some probability.
Currently, I'm overlaying a scatterplot for each cluster, with the size of 'o' markers varying by the probability. This allows easy identification of the most probable cluster, but not much beyond that.
I'd like to draw a scatterplot of pie charts, i.e. one small pie chart for each of the many data points, showing these probabilities. Is that possible in Matlab? I haven't found a way to draw pies as markers or place multiple pie charts at arbitrary positions in one plot…
回答1:
As a first attempt, I managed to draw the pie charts at each point using only two LINE graphic objects: one for the circles, and one for the divisions inside the circles. Thus we are just plotting unfilled pie charts.
This is very efficient in terms of performance. It is achieved by using NaN
to separate the lines into segments. Compare this to the other proposed solution; if we look at its source code, we find that it creates one axis for every single point, and calls MATLAB's function PIE inside it.
We start with some data points along with their "fuzzy clustering":
numPoints = 15; numClasses = 5;
%# random 2D points
points = randn(numPoints,2);
%# fuzzy clustering: probabilistic distribution
prob = rand(numPoints,numClasses);
prob = bsxfun(@rdivide, prob, sum(prob,2));
Now here is the code to plot a scatter of pie charts:
%# pie parameters
theta = linspace(0, 2*pi, 100); %# steps to approximate a circle
r = min(range(points)) / 10; %# radius (determined based on points spread)
%# pie circles
px = bsxfun(@plus, cos(theta).*r, points(:,1))';
py = bsxfun(@plus, sin(theta).*r, points(:,2))';
px(end+1,:) = NaN; py(end+1,:) = NaN;
%# pie divisions
tt = cumsum(prob,2) .* 2*pi;
qx = cat(3, ...
bsxfun(@plus, cos(tt).*r, points(:,1)), ...
repmat(points(:,1), [1 numClasses]), ...
NaN(numPoints,numClasses));
qy = cat(3, ...
bsxfun(@plus, sin(tt).*r, points(:,2)), ...
repmat(points(:,2), [1 numClasses]), ...
NaN(numPoints,numClasses));
qx = permute(qx, [3 2 1]); qy = permute(qy, [3 2 1]);
%# plot
figure
line(px(:), py(:), 'Color','k')
line(qx(:), qy(:), 'Color','k')
axis equal

In my second attempt, I managed to plot colored pie charts by using PATCH function to draw each slice in every circle. Obviously, this implies we are creating a lot more graphics objects compared to before...
We could have used the same NaN
technique to plot same slice from every circle using a single PATCH call, but it proved problematic when the pie charts overlap (specifically the z-order was not correct).
clr = hsv(numClasses); %# colors for each class
r = min(range(points)) / 10; %# radius (determined based on points spread)
tt = cumsum(prob,2) .* 2*pi; %# pie divisions
figure
h = zeros(numPoints,numClasses); %# handles to patches
for idx=1:numPoints %# for each point
for k=1:numClasses %# for each class
%# start/end angle of arc
if k>1
t(1) = tt(idx,k-1);
else
t(1) = 0;
end
t(2) = tt(idx,k);
%# steps to approximate an arc from t1 to t2
theta = linspace(t(1), t(2), 50);
%# slice (line from t2 to center, then to t1, then an arc back to t2)
x = points(idx,1) + r .* [cos(t(2)) ; 0 ; cos(t(1)) ; cos(theta(:))];
y = points(idx,2) + r .* [sin(t(2)) ; 0 ; sin(t(1)) ; sin(theta(:))];
h(idx,k) = patch('XData',x, 'YData',y, ...
'FaceColor',clr(k,:), 'EdgeColor','k');
%# show percentage labels
ind = fix(numel(theta)./2) + 3; %# middle of the arc
text(x(ind), y(ind), sprintf('%.2f%%', prob(idx,k)*100), ...
'Color','k', 'FontSize',6, ...
'VerticalAlign','middle', 'HorizontalAlign','left');
end
end
axis equal
labels = cellstr( num2str((1:numClasses)', 'Cluster %d') );
legend(h(1,:), labels)

If the percentage labels are too much, simply remove the TEXT call above.
回答2:
The Bubble Pie by Abraham Anderson on Matlab File Exchange seems like something relevant to what you are describing.

来源:https://stackoverflow.com/questions/11073889/scatter-pie-plot