MATLAB中数据周围的椭圆

16
我想在MATLAB中重现以下图像: exampleee.png 有两类具有X和Y坐标的点。我想用一个标准差的椭圆来包围每个类,其中一个参数决定了椭圆沿轴如何延伸。
该图是使用另一种软件创建的,我不太理解它如何计算椭圆。
这是我用于此图的数据。第一列是类,第二列是X,第三列是Y。我可以使用gscatter绘制点本身。
A = [
    0   0.89287 1.54987
    0   0.69933 1.81970
    0   0.84022 1.28598
    0   0.79523 1.16012
    0   0.61266 1.12835
    0   0.39950 0.37942
    0   0.54807 1.66173
    0   0.50882 1.43175
    0   0.68840 1.58589
    0   0.59572 1.29311
    1   1.00787 1.09905
    1   1.23724 0.98834
    1   1.02175 0.67245
    1   0.88458 0.36003
    1   0.66582 1.22097
    1   1.24408 0.59735
    1   1.03421 0.88595
    1   1.66279 0.84183
];

gscatter(A(:,2),A(:,3),A(:,1))

顺便提一下,这里是有关如何绘制椭圆的SO问题(链接)。 因此,我们只需要知道绘制它所需的所有参数。


更新:

我同意可以通过计算X和Y坐标的平均值来计算中心。 可能我必须对每个类使用主成分分析 (PRINCOMP) 来确定角度和形状。 还在考虑中...


即使您不知道如何计算原始图形中的椭圆,您也可能解释一下它应该表示什么意思?这不仅仅是像灰色点那样围绕点,而是并非所有点都包含在椭圆中。如果您一无所知,我建议将点的重心作为椭圆的中心作为起点。二阶矩可以给出主轴方向。 - groovingandi
@ groovingandi:基本上意味着,如果用标准差3绘制椭圆,并使用正态分布,它将包含约99%的数据点。图中的椭圆是使用STD = 2生成的。 - yuk
3个回答

17

考虑以下代码:

%# generate data
num = 50;
X = [ mvnrnd([0.5 1.5], [0.025 0.03 ; 0.03 0.16], num) ; ...
      mvnrnd([1 1], [0.09 -0.01 ; -0.01 0.08], num)   ];
G = [1*ones(num,1) ; 2*ones(num,1)];

gscatter(X(:,1), X(:,2), G)
axis equal, hold on

for k=1:2
    %# indices of points in this group
    idx = ( G == k );

    %# substract mean
    Mu = mean( X(idx,:) );
    X0 = bsxfun(@minus, X(idx,:), Mu);

    %# eigen decomposition [sorted by eigen values]
    [V D] = eig( X0'*X0 ./ (sum(idx)-1) );     %#' cov(X0)
    [D order] = sort(diag(D), 'descend');
    D = diag(D);
    V = V(:, order);

    t = linspace(0,2*pi,100);
    e = [cos(t) ; sin(t)];        %# unit circle
    VV = V*sqrt(D);               %# scale eigenvectors
    e = bsxfun(@plus, VV*e, Mu'); %#' project circle back to orig space

    %# plot cov and major/minor axes
    plot(e(1,:), e(2,:), 'Color','k');
    %#quiver(Mu(1),Mu(2), VV(1,1),VV(2,1), 'Color','k')
    %#quiver(Mu(1),Mu(2), VV(1,2),VV(2,2), 'Color','k')
end

截图


编辑

如果您想让椭圆表示特定标准差水平,则正确的方法是通过缩放协方差矩阵来实现:

STD = 2;                     %# 2 standard deviations
conf = 2*normcdf(STD)-1;     %# covers around 95% of population
scale = chi2inv(conf,2);     %# inverse chi-squared with dof=#dimensions

Cov = cov(X0) * scale;
[V D] = eig(Cov);

OP_DATA


此外,您可能想要在MATLAB中查看eigshow演示脚本:http://www.mathworks.com/company/newsletters/news_notes/clevescorner/win98cleve.html - Amro
太好了。非常感谢。我以前不太知道如何使用特征向量/特征值,但现在我可以清楚地看到这些东西是如何工作的。有一点小问题。如果我运行你的代码,我得到的椭圆较小。如果我执行 STD = 2; VV = V*sqrt(D)*STD;,椭圆的大小与你和我原始图中的大小相同。这样做正确吗?这个乘数是否真的对应于其他软件(我用来绘制原始图形的软件)所称的标准差? - yuk
1
@yuk:你对上面的图表是正确的,但正确的做法是通过缩放协方差矩阵来实现。请参见我上面的编辑。 - Amro
1
如果有人偶然发现这篇文章并想在Excel中实现相同的算法,我已经将MatLab示例翻译成了VBA。(https://github.com/Beakerboy/VBA-Projects/blob/master/Ellipse.bas) - Kevin Nowaczyk

2
我会尝试以下方法:
  1. 计算椭圆的中心x-y质心(x,y在链接问题中)。
  2. 计算线性回归拟合线以获取椭圆主轴的方向(角度)。
  3. 计算x和y轴上的标准偏差。
  4. 将x-y标准偏差平移,使其与拟合线正交(a,b)。

能否解释一下为什么要投反对票?我的方法在概念上有问题吗? - Doresoom
这不是我的问题。我还在思考如何实现它。 - yuk
这种方法会得到一个类似的结果(但不完全相同)。线性回归和特征向量之间存在很大的差异,线性回归只考虑y轴上的偏差。计算线性回归、旋转数据并重复此过程可能会得到相同的结果。这将最小化沿着回归线垂直于轴的平方和,而不仅仅是在y轴上。 - Kevin Nowaczyk
@KevinNowaczyk 哇,自从我发布这个答案以来已经有一段时间了!在过去的6-7年里,我处理了更多的特征向量,我会说Amro的答案比线性回归要更有效率。 - Doresoom
我只是在这里留下我的评论,以防其他人遇到这个问题并认为回归会更容易。我曾经使用过你描述的确切过程,在Excel中一段时间,直到我看到了这个帖子。最终,我用VBA复制了最佳答案。 - Kevin Nowaczyk

1
我假设在一个单矩阵中只给出了一组点,例如:
B = A(1:10,2:3);

您可以为每个数据集重复此过程。

  1. 计算椭球体的中心,即点的平均值。Matlab函数:mean
  2. 将数据居中。Matlab函数:bsxfun
  3. 计算椭球体的主轴及其相应的大小。Matlab函数:eig

下面是这些步骤的示例:

Center = mean(B,1);
Centered_data = bsxfun(@minus,B,Center);
[AX,MAG] = eig(Centered_data' * Centered_data);

AX的列包含描述椭球主轴的向量,而MAG的对角线包含有关其大小的信息。 要绘制椭球,请使用其大小的平方根来缩放每个主轴。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接