我正在创建一些数据的散点图,就像你一样,我有一些重复的数据点,我想将它们绘制成具有一些alpha值的圆圈,以便在相同的点上堆积额外的点位置很明显。
据我所知,你无法设置用plot(x, y, 'o')
生成的小圆圈的alpha属性,所以我自己使用patch()
绘制了数千个小圆圈:
x = repmat([1:10], [1 10]);
y = round(10*rand(100, 1))/10;
xlim([0 11])
ylim([0 1])
p = ag_plot_little_circles(x', y, 10, [1 0 .4], 0.2);
function p = ag_plot_little_circles(x, y, circle, col, alpha)
%AG_PLOT_LITTLE_CIRCLES Plot circular circles of relative size circle
% Returns handles to all patches plotted
% aspect is width / height
fPos = get(gcf, 'Position');
% need width, height in data values
xl = xlim();
yl = ylim();
w = circle*(xl(2)-xl(1))/fPos(3);
h = circle*(yl(2)-yl(1))/fPos(4);
theta = 0:pi/5:2*pi;
mx = w*sin(theta);
my = h*cos(theta);
num = 0;
for k = 1:max(size(x))
for f = 1:size(y,2)
num = num+1;
p(num) = patch(x(k)+mx, y(k,f)+my, col, 'FaceColor', col, 'FaceAlpha', alpha, 'EdgeColor', 'none');
end
end
end
正如您所看到的,这不是最佳的,因为在绘制之前我需要知道并设置绘图的大小(xlim
和ylim
),以便圆圈最终成为圆形。如果我重新塑造情节,那么它们最终会成为椭圆形。我最终还有数以百万计的物品,这在传说中是一种痛苦。
有更简单的方法吗?
答案 0 :(得分:4)
我发现无法在MATLAB中使用包含alpha的行标记。
如果你看一下线属性(图中背后的(中)低级函数),你会看到你可以定义标记,它们的唯一属性是它们的颜色(MarkerEdgeColor
或MarkerFaceColor
) ,不带任何alpha(没有MarkerFaceAlpha
属性)。
所以如何使用补丁来实现它似乎是要走的路。
我唯一可以避免拥有数以万计的对象的建议是将它们分组在hggroup中,这会使它们在图例中显示为单个对象。
答案 1 :(得分:3)
我尝试使用patch
执行常规功能。它很慢而且有点儿麻烦,但它适用于简单的情况。 MATLAB需要一个实线alpha。
x
和y
是要绘制的点,w
线宽,col
颜色和a
alpha值。
示例:
x = linspace(-2,2,100);
plotWithAlpha(x,sin(4*x),0.04,'r',0.2)
function [] = plotWithAlpha(x,y,w,col,a)
%function [] = plotWithAlpha(x,y,w,col,a)
if(size(x,1) ~= 1)
x = x.';
end
if(size(x,1) ~= 1)
y = y.';
end
sz = length(x);
% Calculate derrivatives of the curve
X = csaps(1:sz(1),x,1);
Y = csaps(1:sz(1),y,1);
mx = fnval(fnder(X,1),1:sz(1)).';
my = fnval(fnder(Y,1),1:sz(1)).';
T = [mx my]; %tangent
% Normalize tangents
T = bsxfun(@rdivide,T,sqrt(sum(T.^2,2)));
N = zeros(size(T));
N(:,2) = 1;
N(:,1) = -T(:,2)./T(:,1);
N = bsxfun(@rdivide,N,sqrt(sum(N.^2,2)));
N = N.';
hold on
for i = 2:length(x)
X = [x(i-1)+w*N(1,i-1) x(i)+w*N(1,i) x(i-1)-w*N(1,i-1) x(i)-w*N(1,i)];
Y = [y(i-1)+w*N(2,i-1) y(i)+w*N(2,i) y(i-1)-w*N(2,i-1) y(i)-w*N(2,i)];
% Order the points
D = pdist([X' Y']);
D = squareform(D); D(D==0) = Inf;
inds = 1;
D(:,1) = Inf;
[val ind] = min(D(1,:));
inds(2) = ind;
D(:,ind) = Inf;
[val ind] = min(D(ind,:));
inds(3) = ind;
D(:,ind) = Inf;
inds(4) = setxor(inds,1:4);
X = X(inds);
Y = Y(inds);
patch(X,Y,col,'edgeColor','none','FaceAlpha',a)
end
hold off
答案 2 :(得分:3)
我有同样的问题,我的散点图有100,000点。 回答#2的想法很棒,但在Illustrator中打开我的情节对我来说是不切实际的 因为我得分太多了所以我将答案#2改编成批处理过程:
将图形打印到matlab中的pdf文件:
print -dpdf foo.pdf
使用debian package pdf2svg中的pdf2svg将pdf文件转换为svg:
pdf2svg foo.pdf foo.svg
使所有蓝色物体透明:
sed '/rgb(0%,0%,100%)/s/fill-opacity:1/fill-opacity:.2' < foo.svg > foo2.svg
使用debian包中的rsvg-convert将foo2.svg转换为pdf librsvg2斌:
rsvg-convert -f pdf -o foo2.pdf foo2.svg
答案 3 :(得分:2)
据我所知,没有办法直接为MATLAB中的标记设置alpha。当alpha设置低于约0.03或者远远超过10,000个标记时,补丁方法无法正常工作。
当您拥有密集的标记云时,生成发布质量图形的解决方法是为标记提供独特的颜色。然后将图形打印到EPS。然后在Illustrator中打开,选择该颜色的所有对象,并在Illustrator中设置对象的透明度和颜色。它不是人们所希望的一步式解决方案,但它确实提供了比使用内部MATLAB函数更好,更好看的结果,并且快速,只要你有Illustrator或等效的矢量图形包。
答案 4 :(得分:2)
在Matlab Exchange上找到patchline
函数,该函数可以包含patch
个'FaceAlpha'
个参数:
http://www.mathworks.com/matlabcentral/fileexchange/36953-patchline/content/patchline.m