2016-03-23 5 views
2

Ich mache ein sehr einfaches Streudiagramm.Wie macht man MATLAB xlim auto noch symmetrisch um 0?

pts = [1 1; -2 1]; 
scatter(pts(:, 1), pts(:, 2)); 

Wie wir sehen, ist die xlim automatisch von MATLAB bestimmt -2-1 zu sein, die mir zufrieden stellend ist.

Was mich nervt ist, dass der Ursprung 0 nicht zentriert ist. Das ist die x-Achse ist asymmetrisch um 0. In diesem speziellen Beispiel möchte ich, dass die X-Achse von -2 bis 2 ist.

Ich kann sicherlich den größten absoluten Wert finden, der in diesem Fall 2 ist, und manuell tun xlim([-2 2]). Gibt es einen eleganteren Weg, wie axis center in meiner Vorstellung?

+1

Ich glaube nicht, dass es eine 'Achsenmitte'-Option gibt, den größten abs-Wert zu finden und ihn mit' xlim' zu setzen, könnte hier die bessere Methode sein - da alle Funktionen oder Optionen ähnliche Dinge tun. – GameOfThrows

+1

Sie sagten manuell, das ist nicht weit von 'xlim ([- max (abs (x)), max (abs (x))])' (oder in Ihrem Fall 'max (abs (pts (:, 1))) ') – Steve

Antwort

1

Ich denke an zwei Möglichkeiten, dies zu tun die erste ist, die mit Abstand am einfachsten zu verstehen ...

Ihre eigene Streufunktion (ungetestet) ein:

function h = yourScatter (varargin) 
    h = scatter (varargin{:}); 
    xlim(max(abs(h.Parent.XLim)).*[-1 1]) 
end 

Die zweite Zeile ist die gleiche wie in @Daniel Antwort.

Dann nutzen Sie:

pts = [1 1; -2 1]; 
yourScatter(pts(:, 1), pts(:, 2));  

Verwendung undokumentierte Zuhörer

Je komplexer und vollautomatisierte Verfahren einige undokumentierte Zuhörer ausführen verwenden.

1. wir eine Funktion erstellen, die wir die Achsen zu schaffen, verwenden (Diese Funktion hat einen Hörer, der die Unterfunktionsaufrufe, wo die tatsächlichen Grenzen gesetzt sind Post, den Sie Daten hinzugefügt):

function ax = setupAutoXAxis 
    ax = axes ('nextplot', 'add'); 
    addlistener (ax, 'MarkedClean', @updateAx); 
end 
function updateAx (ax, event) 
    % check that any children have been added 
    if ~isempty (ax.Children) 
    % extract out all children XData 
    currentLim = max(abs([ax.Children.XData])); 
    % Check to see if it needs to be updated. 
    if ~isempty (currentLim) && ~isequal (ax.XLim, [-currentLim currentLim]) 
     ax.XLim = [-currentLim currentLim]; 
    end 
    end 
end 

Sie dann diese verwenden etwa so:

ax = setupAutoXAxis() 
pts = [1 1; -2 1]; 
scatter (ax, pts(:,1), pts(:,2)); 

Leider funktioniert das nicht für mehr Plots Zugabe - das ist, weil durch die Grenzen Einstellung manuell das MarkedClean Ereignis nicht ausgelöst wird (was ich war überrascht von). Ich habe nachgesehen und die beste Lösung, die ich bekommen kann, besteht darin, einen anderen Listener hinzuzufügen, der das MarkedClean-Ereignis auslöst (Das ChildAdded-Ereignis wird ausgelöst, bevor die eigentlichen Kinddaten hinzugefügt werden, so dass wir das nicht verwenden können).

function ax = setupAutoXAxis 
    ax = axes ('nextplot', 'add'); 
    addlistener (ax, 'ChildAdded', @(a,b)set(ax,'XLimMode','auto')); 
    addlistener (ax, 'MarkedClean', @updateAx); 
end 
function updateAx (ax, event) 
    % check that any children have been added 
    if ~isempty (ax.Children) 
    % extract out all children XData 
    currentLim = max(abs([ax.Children.XData])); 
    % Check to see if it needs to be updated. 
    if ~isempty (currentLim) && ~isequal (ax.XLim, [-currentLim currentLim]) 
     ax.XLim = [-currentLim currentLim]; 
    end 
    end 
end 

ax = setupAutoXAxis() 
pts = [1 1; -2 1]; 
scatter (ax, pts(:,1), pts(:,2)); 
scatter (ax, pts(:,1)+3, pts(:,2)); 

Für Info wurde dies auf R2015a getestet.

2

Nach meinem Wissen gibt es keinen Automatismus. Sie müssen es manuell tun. Für eine individuelle Achse können Sie:

xlim(max(abs(xlim)).*[-1 1]) 

Für eine einzelne Codezeile, die es für alle tut (2 oder 3) Achse Verwendung:

axis(reshape([-1;1]*max(reshape(abs(axis),2,[])),1,[]))