2010-08-05 46 views
15

Je voudrais reproduire la figure suivante dans Matlab:Ellipse autour des données dans MATLAB®

exampleee.png

Il y a deux classes de points avec les coordonnées X et Y. Je voudrais entourer chaque classe d'une ellipse avec un paramètre d'écart type, qui détermine à quelle distance l'ellipse ira le long de l'axe.

La figure a été créée avec un autre logiciel et je ne comprends pas exactement comment elle calcule l'ellipse.

Voici les données que j'utilise pour cette figure. La 1ère colonne est la classe, 2ème - X, 3ème - Y. Je peux utiliser gscatter pour dessiner les points lui-même.

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)) 

Pour votre information, here est la question SO sur la façon de dessiner une ellipse. Donc, nous avons juste besoin de connaître tous les paramètres pour le dessiner.


Update:

J'accepte que le centre peut être calculé que les moyens de coordonnées X et Y. Probablement je dois utiliser l'analyse de composant principale (PRINCOMP) pour chaque classe pour déterminer l'angle et la forme. Toujours en pensant ...

+0

Même si vous ne savez pas comment l'ellipse dans la figure originale est calculée, vous pouvez probablement expliquer un peu plus ce qu'il est censé dire? Ce n'est pas juste entourant les points comme pour les points gris par exemple, tous les points ne sont pas inclus dans l'ellipse. Si vous ne savez rien, je suggérerais comme point de départ le barycentre des points comme le centre de l'ellipse. Le deuxième moment de la zone pourrait vous donner la direction de l'axe principal. – groovingandi

+0

@groovingandi: Fondamentalement, cela signifie que si l'ellipse est dessinée avec l'écart-type 3, avec une distribution normale, elle inclura environ 99% des points de données. Les ellipses sur la figure ont été générées avec STD = 2. – yuk

Répondre

17

Tenir compte du code:

%# 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 

screenshot


EDIT

Si vous voulez l'ellipse pour représenter un niveau spécifique de l'écart-type, la bonne façon de faire est en mettant à l'échelle la matrice de covariance:

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

+0

Aussi, vous voudrez peut-être consulter le script de démonstration 'eigshow' dans MATLAB: http://www.mathworks.com/company/newsletters/news_notes/clevescorner/win98cleve.html – Amro

+0

C'est génial. Merci beaucoup. Je ne savais pas trop comment utiliser eigenvector/eigenvalues, mais maintenant je peux voir clairement comment ça fonctionne. La chose mineure. Si je cours votre code, j'obtiens des ellipses plus petites. Si je fais 'STD = 2; VV = V * sqrt (D) * STD; ', les ellipses sont de la même taille que sur votre et mon intrigue originale. Est-ce correct? Ce multiplicateur correspond-il vraiment à ce que l'autre logiciel (j'ai utilisé pour dessiner la figure originale) appelle l'écart-type? – yuk

+1

@yuk: vous avez raison sur la figure ci-dessus, mais la façon correcte de le faire est de mettre à l'échelle la matrice de covariance. S'il vous plaît voir ma modification ci-dessus – Amro

2

Je vais essayer l'approche suivante:

  1. Calculer le xy barycentre pour le centre de l'ellipse (x, y dans le linked question)
  2. Calculer la régression linéaire ligne d'ajustement pour obtenir l'orientation du grand axe de l'ellipse (angle)
  3. Calculer l'écart-type dans les axes x et y
  4. Traduire les écarts-types xy ils sont donc orthogonal à la ligne de coupe (a, b)
+0

Vous voulez expliquer le downvote? Y a-t-il quelque chose de mal conceptuel dans mon approche? – Doresoom

+0

Ce n'était pas moi. Je pense toujours à la mettre en œuvre. – yuk

+0

Cette approche donnerait un résultat semblable (mais pas identique). Il y a de grandes différences entre une régression linéaire, où l'écart n'est pris en compte que dans l'axe y, et le vecteur propre. Il est possible que le calcul de la régression linéaire, la rotation des données et la répétition de ce processus donnent un résultat identique. Ce serait minimiser la somme des carrés le long d'un axe perpendiculaire à la ligne de régression au lieu de seulement dans l'axe des ordonnées. –

1

Je suppose qu'il n'y a qu'un seul ensemble de points donnés dans une seule matrice, par ex.

B = A(1:10,2:3); 

Vous pouvez reproduire cette procédure pour chaque ensemble de données.

  1. Calculez le centre de l'ellipsoïde, qui est la moyenne des points. Fonction Matlab: mean
  2. Centrez vos données. Fonction Matlab bsxfun
  3. Calculer l'axe principal de l'ellipsoïde et leur amplitude respective. fonction Matlab: eig

Les étapes successives sont illustrées ci-dessous:

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

Les colonnes de AX contient des vecteurs décrivant l'axe principal de l'ellipsoïde tandis que la diagonale de MAG contient des informations sur leur ampleur. Pour tracer l'ellipsoïde, mettez à l'échelle chaque axe principal avec la racine carrée de sa magnitude.

Espérons que cela aide.

A.