Was ist Ihr Lieblings-MATLAB / Octave-Programmiertrick? [geschlossen]
73
Ich denke, jeder würde zustimmen, dass die MATLAB-Sprache nicht hübsch oder besonders konsistent ist. Aber das macht nichts! Wir müssen es noch benutzen, um Dinge zu erledigen.
Was sind deine Lieblingstricks, um die Dinge einfacher zu machen? Lassen Sie uns eine pro Antwort haben, damit die Leute sie abstimmen können, wenn sie zustimmen. Versuchen Sie auch, Ihre Antwort anhand eines Beispiels zu veranschaulichen.
In Matlab können Sie die Funktion find verwenden, um im Grunde das Gleiche zu tun.
devin
10
Aber finden ist viel langsamer. Die logische Indizierung ist viel schneller, es sei denn, Sie müssen die Indizes der Übereinstimmungen kennen.
Marc
28
Bieten Sie schnellen Zugriff auf andere Funktionsdokumentationen, indem Sie den Hilfekommentaren eine Zeile "SIEHE AUCH" hinzufügen. Zunächst müssen Sie den Namen der Funktion in Großbuchstaben als erste Kommentarzeile einfügen. Machen Sie Ihre üblichen Kommentar-Header-Sachen und setzen Sie dann SEE ALSO mit einer durch Kommas getrennten Liste anderer verwandter Funktionen.
functiony = transmog(x)%TRANSMOG Transmogrifies a matrix X using reverse orthogonal eigenvectors%% Usage:% y = transmog(x)%% SEE ALSO% UNTRANSMOG, TRANSMOG2
Wenn Sie in der Befehlszeile "help transmog" eingeben, werden alle Kommentare in diesem Kommentar-Header mit Hyperlinks zu den Kommentar-Headern für die anderen aufgelisteten Funktionen angezeigt.
Wie würden Sie es für eine Submatrix tun? Sagen wir: x = rand (20, 20); Ich möchte x (1:10, 1:10) in einen Vektor verwandeln. Sind y = Umformung (x (: 10, 1:10), [], 1) oder y = x (1:10, 1:10) -> y = y (:) meine einzigen Optionen? Unnötig zu sagen, dass x (1:10, 1:10) (:) nicht funktioniert.
Royi
@Drazick, Sie können auf die Elemente von x zugreifen, indem Sie mehrdimensionale Angaben oder einen eindimensionalen Index verwenden. myElems = [1:10 21:30 31:40...181:190]; y = x(myElems);
Scottie T
Angenommen, ich habe ein Bild - I. Um die Varianz zu berechnen, würde ich Folgendes tun: var (I (:)). Was ist, wenn ich die Varianz eines Teils davon berechnen möchte - I (1:20, 1:20). var (var (I (1:20, 1:20)) wird es nicht tun (es ist falsch). Die Optionen, die ich kenne, y = I (1:20, 1:20) -> var (y (: )) oder y = umformen (I (1:20, 1:20), [], 1) -> var (y (:)). Ich frage, ob es eine Möglichkeit gibt, den Doppelpunktoperator auf Untermatrizen anzuwenden einer Matrix ohne sie neu
zuzuweisen
@ Drake: Du solltest das zu einer separaten Frage machen. Vielleicht sub2indkönnte auch helfen
Tobias Kienzler
@ Drazick: feval (@ (x) x (:), x (1: 3,1: 3))
Szymon Bęczkowski
22
Vektorisierungsschleifen . Es gibt viele Möglichkeiten, dies zu tun, und es ist unterhaltsam, nach Schleifen in Ihrem Code zu suchen und zu sehen, wie sie vektorisiert werden können. Die Leistung ist mit Vektoroperationen erstaunlich schneller!
Ist dies jetzt noch der Fall, da Matlab einen JIT-Compiler hat? Es wäre interessant zu sehen.
Matt
20
Anonyme Funktionen aus mehreren Gründen:
um eine schnelle Funktion für einmalige Zwecke wie 3x ^ 2 + 2x + 7 zu erstellen. (siehe Liste unten) Dies ist nützlich für Funktionen wie quadund fminbnd, die Funktionen als Argumente verwenden. Dies ist auch in Skripten (.m-Dateien, die nicht mit einem Funktionsheader beginnen) praktisch, da Sie im Gegensatz zu echten Funktionen keine Unterfunktionen einschließen können.
für Schließungen - obwohl anonyme Funktionen ein wenig einschränkend sind, da es keine Möglichkeit zu geben scheint, eine Zuordnung zum mutierten Zustand in sich zu haben.
.
% quick functions
f = @(x) 3*x.^2 + 2*x + 7;
t = (0:0.001:1);
plot(t,f(t),t,f(2*t),t,f(3*t));
% closures (linfunc below is a function that returns a function,% and the outer functions arguments are held for the lifetime% of the returned function.
linfunc = @(m,b) @(x) m*x+b;
C2F = linfunc(9/5, 32);
F2C = linfunc(5/9, -32*5/9);
M = rand(1000, 1000);
v = rand(1000, 1);
c = bsxfun(@plus, M, v);
Dieser Code fügt beispielsweise den Spaltenvektor v zu jeder Spalte der Matrix M hinzu.
In leistungskritischen Teilen Ihrer Anwendung sollten Sie diese Funktionen jedoch mit der trivialen for-Schleife vergleichen, da Schleifen häufig noch schneller sind.
LaTeX-Modus für Formeln in Diagrammen : In einer der jüngsten Versionen (R2006?) Fügen Sie die zusätzlichen Argumente ,'Interpreter','latex'am Ende eines Funktionsaufrufs hinzu und es wird LaTeX-Rendering verwendet. Hier ist ein Beispiel:
Ich bin mir nicht sicher, wann sie es hinzugefügt haben, aber es funktioniert mit R2006b in den Funktionen text (), title (), xlabel (), ylabel (), zlabel () und sogar legend (). Stellen Sie einfach sicher, dass die von Ihnen verwendete Syntax nicht mehrdeutig ist (daher müssen Sie bei legend () die Zeichenfolgen als Zellenarray angeben).
Matlab gibt jedoch einen Fehler in Ihrem Beispiel aus, da die an den plotBefehl übergebenen Vektoren nicht dieselbe Länge haben. Ich nehme an, Sie versuchen zwei Linien zu zeichnen, oder? Sie benötigen ein Semikolon in der Matrix, das an Ihren Plotbefehl übergeben wird, damit Matlab weiß, dass es sich um zwei separate Serien handelt, dh wie folgt:plot(t,sin(2*pi*[t ; t+0.25]));
Ricardo Altamirano
17
Zeichnen Sie mit xlim und ylim vertikale und horizontale Linien. Beispiele:
Das funktioniert nicht immer. Die Grenzwerte werden nicht in Echtzeit aktualisiert. In diesem Fall drawnowwird es durch einen Aufruf gezwungen, sie zu aktualisieren.
Memming
16
Hier ist ein kurzes Beispiel:
Ich finde die durch Kommas getrennte Listensyntax sehr nützlich, um Funktionsaufrufe zu erstellen:
% Build a list of args, like so:
args = {'a', 1, 'b', 2};
% Then expand this into arguments:
output = func(args{:})
Sie sind sich bei MATLAB nicht sicher, aber in Octave können Sie mehreren Variablen auf ähnliche Weise Werte zuweisen:[one two three four] = {1 2 3 4}{:}
Griffin
11
Hier sind einige nicht offensichtliche Funktionen, die von Zeit zu Zeit nützlich sind:
mfilename (Gibt den Namen des aktuell ausgeführten MATLAB-Skripts zurück.)
dbstack (gibt Ihnen Zugriff auf die Namen und Zeilennummern des Matlab-Funktionsstapels)
keyboard (Stoppt die Ausführung und gibt der Debugging-Eingabeaufforderung die Kontrolle. Aus diesem Grund enthält die Debug-Eingabeaufforderung ein K. K>>
dbstop error (Versetzt Sie automatisch in den Debug-Modus, der an der Zeile angehalten wird, die einen Fehler auslöst.)
Ich benutze aus vielen Gründen gerne Funktionsgriffe. Zum einen sind sie den Zeigern am nächsten, die ich in MATLAB gefunden habe, sodass Sie ein referenzähnliches Verhalten für Objekte erstellen können. Es gibt ein paar nette (und einfachere) Dinge, die Sie auch damit machen können. Beispiel: Ersetzen einer switch-Anweisung:
Verwenden von nargin zum Festlegen von Standardwerten für optionale Argumente und Verwenden von nargout zum Festlegen optionaler Ausgabeargumente. Schnelles Beispiel
functionhLine=myplot(x,y,plotColor,markerType)% set defaults for optional paramtersif nargin<4, markerType='none'; endif nargin<3, plotColor='k'; end
hL = plot(x,y,'linetype','-', ...
'color',plotColor, ...
'marker',markerType, ...
'markerFaceColor',plotColor,'markerEdgeColor',plotColor);
% return handle of plot object if requiredif nargout>0, hLine = hL; end
Ich finde Funktionen einfacher zu pflegen, wenn sie verwendet werden if exist('plotColor', 'var') ..., weil Sie dann den Namen des Arguments und nicht nur dessen Argumentnummer verwenden.
Kennen Sie Ihre Achseneigenschaften ! Es gibt alle möglichen Dinge, die Sie einstellen können, um die Standard-Plot-Eigenschaften zu optimieren, um das zu tun, was Sie wollen:
(Setzt beispielsweise die Schriftgröße auf 8pt, die Linienstile aller neuen Linien auf fest und ihre Breite auf 0,3pt und die xtick-Punkte auf [1 3 5 7 9])
Linien- und Figureneigenschaften sind ebenfalls nützlich, aber ich verwende am häufigsten Achseneigenschaften.
Seien Sie streng bei der Angabe von Dimensionen, wenn Sie Aggregationsfunktionen wie min, max, mean, diff, sum, any, all, ... verwenden.
Zum Beispiel die Zeile:
reldiff = diff(a) ./ a(1:end-1)
funktioniert möglicherweise gut, um relative Unterschiede von Elementen in einem Vektor zu berechnen. Wenn der Vektor jedoch zu nur einem Element degeneriert, schlägt die Berechnung fehl:
>> a=rand(1,7);
>> diff(a) ./ a(1:end-1)
ans =
-0.5822-0.9935224.20150.2708-0.33280.0458
>> a=1;
>> diff(a) ./ a(1:end-1)
??? Error using ==> rdivide
Matrix dimensions must agree.
Wenn Sie für Ihre Funktionen die richtigen Abmessungen angeben, gibt diese Zeile eine leere 1-mal-0-Matrix zurück, die korrekt ist:
Gleiches gilt für eine Min-Funktion, die normalerweise Minima über Spalten in einer Matrix berechnet, bis die Matrix nur noch aus einer Zeile besteht. - Dann wird das Minimum über die Zeile zurückgegeben, sofern der Dimensionsparameter nichts anderes angibt, und wahrscheinlich wird Ihre Anwendung beschädigt.
Ich kann Ihnen fast garantieren, dass Sie durch das Festlegen der Dimensionen dieser Aggregationsfunktionen später einige Debugging-Arbeiten sparen.
Zumindest wäre das bei mir der Fall gewesen. :) :)
lastSix = y (Ende-5: Ende); Ihre Version gibt 7 Elemente zurück.
Jonas
5
Um eine Funktion schnell testen zu können, benutze ich Folgendes nargin:
functionresult = multiply(a, b)if nargin == 0%no inputs provided, run using defaults for a and b
clc;
disp('RUNNING IN TEST MODE')
a = 1;
b = 2;
end
result = a*b;
Später füge ich ein Unit-Test-Skript hinzu, um die Funktion für verschiedene Eingabebedingungen zu testen.
Verwenden von ismember () zum Zusammenführen von Daten, die nach Textkennungen organisiert sind. Nützlich, wenn Sie unterschiedliche Zeiträume analysieren, in denen Einträge, in meinem Fall Firmensymbole, kommen und gehen.
%Merge B into A based on Text identifiers
UniverseA = {'A','B','C','D'};
UniverseB = {'A','C','D'};
DataA = [20406080];
DataB = [305070];
MergeData = NaN(length(UniverseA),2);
MergeData(:,1) = DataA;
[tf, loc] = ismember(UniverseA, UniverseB);
MergeData(tf,2) = DataB(loc(tf));
MergeData =
203040 NaN
60508070
Ausführen eines Simulink-Modells direkt aus einem Skript (anstatt interaktiv) mit dem simBefehl. Sie können beispielsweise Parameter aus einer Arbeitsbereichsvariablen übernehmen und wiederholt simin einer Schleife ausführen , um etwas zu simulieren, während Sie den Parameter variieren, um zu sehen, wie sich das Verhalten ändert, und die Ergebnisse mit beliebigen grafischen Befehlen grafisch darstellen. Viel einfacher als dies interaktiv zu versuchen, und es gibt Ihnen viel mehr Flexibilität als die Simulink "Oszilloskop" -Blöcke bei der Visualisierung der Ergebnisse. (obwohl Sie es nicht verwenden können, um zu sehen, was in Echtzeit passiert, während die Simulation ausgeführt wird)
Eine wirklich wichtige Sache zu wissen ist die DstWorkspaceund SrcWorkspaceOptionen des simsetBefehls. Diese steuern, wo die Blöcke "To Workspace" und "From Workspace" ihre Ergebnisse abrufen und ablegen. DstworkspaceDer Standardwert ist der aktuelle Arbeitsbereich (z. B. wenn Sie siminnerhalb einer Funktion aufrufen, werden die Blöcke "To Workspace" als Variablen SrcWorkspaceangezeigt, auf die innerhalb derselben Funktion zugegriffen werden kann). Der Standardwert ist jedoch der Basisarbeitsbereich, und wenn Sie Ihren Anruf an simSie kapseln möchten möchten einstellen SrcWorkspace, currentdamit es eine saubere Schnittstelle zum Bereitstellen / Abrufen von Simulationseingabeparametern und -ausgaben gibt. Zum Beispiel:
functionY=run_my_sim(t,input1,params)% runs "my_sim.mdl" % with a From Workspace block referencing I1 as an input signal% and parameters referenced as fields of the "params" structure% and output retrieved from a To Workspace block with name O1.
opt = simset('SrcWorkspace','current','DstWorkspace','current');
I1 = struct('time',t,'signals',struct('values',input1,'dimensions',1));
Y = struct;
Y.t = sim('my_sim',t,opt);
Y.output1 = O1.signals.values;
Konturdiagramme mit [c,h]=contourund clabel(c,h,'fontsize',fontsize). Normalerweise benutze ich den fontsizeParameter, um die Schriftgröße zu reduzieren, damit die Zahlen nicht ineinander laufen. Dies ist ideal, um den Wert von 2D-Funktionen anzuzeigen, ohne mit 3D-Diagrammen herumspielen zu müssen.
functioniNeedle = findClosest(hay,needle)%FINDCLOSEST find the indicies of the closest elements in an array.% Given two vectors [A,B], findClosest will find the indicies of the values% in vector A closest to the values in vector B.
[hay iOrgHay] = sort(hay(:)'); %#ok must have row vector% Use histogram to find indices of elements in hay closest to elements in% needle. The bins are centered on values in hay, with the edges on the% midpoint between elements.
[iNeedle iNeedle] = histc(needle,[-inf hay+[diff(hay)/2inf]]); %#ok% Reversing the sorting.
iNeedle = iOrgHay(iNeedle);
Verwenden von persistent(statischen) Variablen beim Ausführen eines Online-Algorithmus. Dies kann den Code in Bereichen wie dem maschinellen Lernen nach Bayes beschleunigen, in denen das Modell iterativ für die neuen Beispiele trainiert wird. Zum Berechnen der unabhängigen Loglikelihoods berechne ich beispielsweise die Loglikelihood zunächst von Grund auf neu und aktualisiere sie, indem ich diese zuvor berechnete Loglikelihood und die zusätzliche Loglikelihood summiere.
Anstatt ein spezielleres Problem des maschinellen Lernens anzugeben, möchte ich einen allgemeinen Online-Mittelungscode angeben, den ich von hier übernommen habe :
functionav = runningAverage(x)% The number of values entered so far - declared persistent.persistent n;
% The sum of values entered so far - declared persistent.persistent sumOfX;
if x == 'reset'% Initialise the persistent variables.
n = 0;
sumOfX = 0;
av = 0;
else% A data value has been added.
n = n + 1;
sumOfX = sumOfX + x;
av = sumOfX / n; % Update the running average.end
Die Aufrufe ergeben dann die folgenden Ergebnisse
runningAverage('reset')
ans = 0
>> runningAverage(5)
ans = 5
>> runningAverage(10)
ans = 7.5000
>> runningAverage(3)
ans = 6
>> runningAverage('reset')
ans = 0
>> runningAverage(8)
ans = 8
persistentist gefährlich, da Sie den internen Status nicht direkt festlegen können, was bedeutet, dass Sie nicht richtig testen können. Dies bedeutet auch, dass Sie die Funktion jeweils nur an einem Ort verwenden können. Wenn Sie beispielsweise laufende Durchschnittswerte von zwei getrennten Größen berechnen möchten, müssen Sie die Datei kopieren, um die Zustände zu trennen.
Nzbuu
Es ist wahr, dass wir es vermeiden sollten, wenn es nicht hilft, da es zu unerwarteten Problemen führen kann, die schwer zu bemerken sind. In meinem Problem nehme ich einige Online-Änderungen an wenigen Variablen vor, um die Geschwindigkeit des Codes erheblich zu verbessern. Man sollte es mit Vorsicht verwenden.
Petrichor
2
Ich bin überrascht, dass, während die Leute den logischen Array-Ansatz der Indizierung eines Arrays erwähnten, niemand den Befehl find erwähnte.
zB wenn x ein NxMxO-Array ist
x (x> 20) generiert ein logisches NxMxO-Array und indiziert damit x (was schlecht sein kann, wenn Sie große Arrays haben und nach einer kleinen Teilmenge suchen
x (find (x> 20)) generiert eine Liste (dh 1xwas auch immer) von Indizes von x, die x> 20 erfüllen, und indiziert x damit. "find" sollte meiner Erfahrung nach mehr verwendet werden als es ist.
Mehr, was ich "Tricks" nennen würde
Sie können Arrays und Zellenarrays vergrößern / anhängen, wenn Sie die benötigte Größe nicht kennen, indem Sie end + 1 verwenden (funktioniert auch mit höheren Dimensionen, solange die Dimensionen des Slice übereinstimmen - so werden Sie müssen x in diesem Fall mit etwas anderem als [] initialisieren). Nicht gut für Zahlen, aber für kleine dynamische Listen von Dingen (oder Zellenarrays), z. B. Parsen von Dateien.
z.B
>> x = [1,2,3]
x = 1 2 3
>> x (Ende + 1) = 4
x = 1 2 3 4
Ein anderer Gedanke, den viele Leute nicht wissen, ist, dass für Arbeiten an einem dim 1-Array, um das Beispiel fortzusetzen
>> für n = x; disp (n); end
1
2
3
4
Das heißt, wenn Sie nur die Mitglieder von x benötigen, müssen Sie sie nicht indizieren.
Dies funktioniert auch mit Zellenarrays, ist jedoch etwas ärgerlich, da das Element beim Gehen immer noch in eine Zelle eingeschlossen ist:
>> für el = {1,2,3,4}; disp (el); end
[1]
[2]
[3]
[4]
Um an die Elemente zu gelangen, müssen Sie sie abonnieren
>> für el = {1,2,3,4}; disp (el {1}); end
1
2
3
4
Ich kann mich nicht erinnern, ob es einen schöneren Weg gibt, das zu umgehen.
Die Verwendung findin diesen Situationen ist eine schlechte Idee, da sie redundant und langsamer ist. Persönlich finde ich den logischen Ansatz klarer, weil er auch die zusätzliche Unordnung vermeidet.
Nzbuu
2
-Sie können eine Matlab-Verknüpfung zu einer Initialisierungsdatei namens startup.m erstellen. Hier definiere ich Formatierung, Genauigkeit der Ausgabe und Plotparameter für meine Matlab-Sitzung (z. B. verwende ich eine größere Plotachse / Schriftgröße, damit .figs deutlich sichtbar sind, wenn ich sie in Präsentationen einfüge.) Blog-Post von einem der Entwickler darüber http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/ .
-Sie können eine ganze numerische ASCII-Datei mit der Funktion "Laden" laden. Dies ist nicht besonders schnell, erledigt aber die Arbeit für das Prototyping schnell (sollte das nicht das Motto von Matlab sein?)
- Wie bereits erwähnt, sind der Doppelpunktoperator und die Vektorisierung Lebensretter. Schraubenschlaufen.
und wenn x 3D ist, dann brauchen Sie eine andere Summe (), um N zu berechnen. Ich würde N = sum(I(:));stattdessen verwenden, arbeitet mit jeder Dimensionalität.
Bieten Sie schnellen Zugriff auf andere Funktionsdokumentationen, indem Sie den Hilfekommentaren eine Zeile "SIEHE AUCH" hinzufügen. Zunächst müssen Sie den Namen der Funktion in Großbuchstaben als erste Kommentarzeile einfügen. Machen Sie Ihre üblichen Kommentar-Header-Sachen und setzen Sie dann SEE ALSO mit einer durch Kommas getrennten Liste anderer verwandter Funktionen.
function y = transmog(x) %TRANSMOG Transmogrifies a matrix X using reverse orthogonal eigenvectors % % Usage: % y = transmog(x) % % SEE ALSO % UNTRANSMOG, TRANSMOG2
Wenn Sie in der Befehlszeile "help transmog" eingeben, werden alle Kommentare in diesem Kommentar-Header mit Hyperlinks zu den Kommentar-Headern für die anderen aufgelisteten Funktionen angezeigt.
quelle
Verwandeln Sie eine Matrix mit einem Doppelpunkt in einen Vektor.
x = rand(4,4); x(:)
quelle
myElems = [1:10 21:30 31:40...181:190]; y = x(myElems);
sub2ind
könnte auch helfenVektorisierungsschleifen . Es gibt viele Möglichkeiten, dies zu tun, und es ist unterhaltsam, nach Schleifen in Ihrem Code zu suchen und zu sehen, wie sie vektorisiert werden können. Die Leistung ist mit Vektoroperationen erstaunlich schneller!
quelle
Anonyme Funktionen aus mehreren Gründen:
quad
undfminbnd
, die Funktionen als Argumente verwenden. Dies ist auch in Skripten (.m-Dateien, die nicht mit einem Funktionsheader beginnen) praktisch, da Sie im Gegensatz zu echten Funktionen keine Unterfunktionen einschließen können..
% quick functions f = @(x) 3*x.^2 + 2*x + 7; t = (0:0.001:1); plot(t,f(t),t,f(2*t),t,f(3*t)); % closures (linfunc below is a function that returns a function, % and the outer functions arguments are held for the lifetime % of the returned function. linfunc = @(m,b) @(x) m*x+b; C2F = linfunc(9/5, 32); F2C = linfunc(5/9, -32*5/9);
quelle
Matlab bsxfun , arrayfun , cellfun und structfun sind sehr interessant und oft speichern einer Schleife.
M = rand(1000, 1000); v = rand(1000, 1); c = bsxfun(@plus, M, v);
Dieser Code fügt beispielsweise den Spaltenvektor v zu jeder Spalte der Matrix M hinzu.
In leistungskritischen Teilen Ihrer Anwendung sollten Sie diese Funktionen jedoch mit der trivialen for-Schleife vergleichen, da Schleifen häufig noch schneller sind.
quelle
LaTeX-Modus für Formeln in Diagrammen : In einer der jüngsten Versionen (R2006?) Fügen Sie die zusätzlichen Argumente
,'Interpreter','latex'
am Ende eines Funktionsaufrufs hinzu und es wird LaTeX-Rendering verwendet. Hier ist ein Beispiel:t=(0:0.001:1); plot(t,sin(2*pi*[t ; t+0.25])); xlabel('t'); ylabel('$\hat{y}_k=sin 2\pi (t+{k \over 4})$','Interpreter','latex'); legend({'$\hat{y}_0$','$\hat{y}_1$'},'Interpreter','latex');
Ich bin mir nicht sicher, wann sie es hinzugefügt haben, aber es funktioniert mit R2006b in den Funktionen text (), title (), xlabel (), ylabel (), zlabel () und sogar legend (). Stellen Sie einfach sicher, dass die von Ihnen verwendete Syntax nicht mehrdeutig ist (daher müssen Sie bei legend () die Zeichenfolgen als Zellenarray angeben).
quelle
plot
Befehl übergebenen Vektoren nicht dieselbe Länge haben. Ich nehme an, Sie versuchen zwei Linien zu zeichnen, oder? Sie benötigen ein Semikolon in der Matrix, das an Ihren Plotbefehl übergeben wird, damit Matlab weiß, dass es sich um zwei separate Serien handelt, dh wie folgt:plot(t,sin(2*pi*[t ; t+0.25]));
Zeichnen Sie mit xlim und ylim vertikale und horizontale Linien. Beispiele:
Zeichnen Sie eine horizontale Linie bei y = 10:
line(xlim, [10 10])
Zeichnen Sie eine vertikale Linie bei x = 5:
line([5 5], ylim)
quelle
drawnow
wird es durch einen Aufruf gezwungen, sie zu aktualisieren.Hier ist ein kurzes Beispiel:
Ich finde die durch Kommas getrennte Listensyntax sehr nützlich, um Funktionsaufrufe zu erstellen:
% Build a list of args, like so: args = {'a', 1, 'b', 2}; % Then expand this into arguments: output = func(args{:})
quelle
[one two three four] = {1 2 3 4}{:}
Hier sind einige nicht offensichtliche Funktionen, die von Zeit zu Zeit nützlich sind:
mfilename
(Gibt den Namen des aktuell ausgeführten MATLAB-Skripts zurück.)dbstack
(gibt Ihnen Zugriff auf die Namen und Zeilennummern des Matlab-Funktionsstapels)keyboard
(Stoppt die Ausführung und gibt der Debugging-Eingabeaufforderung die Kontrolle. Aus diesem Grund enthält die Debug-Eingabeaufforderung ein K.K>>
dbstop error
(Versetzt Sie automatisch in den Debug-Modus, der an der Zeile angehalten wird, die einen Fehler auslöst.)quelle
Ich benutze aus vielen Gründen gerne Funktionsgriffe. Zum einen sind sie den Zeigern am nächsten, die ich in MATLAB gefunden habe, sodass Sie ein referenzähnliches Verhalten für Objekte erstellen können. Es gibt ein paar nette (und einfachere) Dinge, die Sie auch damit machen können. Beispiel: Ersetzen einer switch-Anweisung:
switch number, case 1, outargs = fcn1(inargs); case 2, outargs = fcn2(inargs); ... end % %can be turned into % fcnArray = {@fcn1, @fcn2, ...}; outargs = fcnArray{number}(inargs);
Ich finde solche kleinen Dinge einfach cool.
quelle
Verwenden von nargin zum Festlegen von Standardwerten für optionale Argumente und Verwenden von nargout zum Festlegen optionaler Ausgabeargumente. Schnelles Beispiel
function hLine=myplot(x,y,plotColor,markerType) % set defaults for optional paramters if nargin<4, markerType='none'; end if nargin<3, plotColor='k'; end hL = plot(x,y,'linetype','-', ... 'color',plotColor, ... 'marker',markerType, ... 'markerFaceColor',plotColor,'markerEdgeColor',plotColor); % return handle of plot object if required if nargout>0, hLine = hL; end
quelle
if exist('plotColor', 'var') ...
, weil Sie dann den Namen des Arguments und nicht nur dessen Argumentnummer verwenden.Aufrufen von Java-Code aus Matlab
quelle
cellfun und arrayfun für automatisierte for-Schleifen.
quelle
Oh, und ein Array umkehren
v = 1:10; v_reverse = v(length(v):-1:1);
quelle
flipud()
oder diesfliplr()
tun. In Kombination mit Schritten ist dies jedoch nützlicher. zB v (Ende: -4: 1) zum Beispiel.Bedingte Argumente auf der linken Seite einer Aufgabe:
t = (0:0.005:10)'; x = sin(2*pi*t); x(x>0.5 & t<5) = 0.5; % This limits all values of x to a maximum of 0.5, where t<5 plot(t,x);
quelle
Kennen Sie Ihre Achseneigenschaften ! Es gibt alle möglichen Dinge, die Sie einstellen können, um die Standard-Plot-Eigenschaften zu optimieren, um das zu tun, was Sie wollen:
set(gca,'fontsize',8,'linestyleorder','-','linewidth',0.3,'xtick',1:2:9);
(Setzt beispielsweise die Schriftgröße auf 8pt, die Linienstile aller neuen Linien auf fest und ihre Breite auf 0,3pt und die xtick-Punkte auf [1 3 5 7 9])
Linien- und Figureneigenschaften sind ebenfalls nützlich, aber ich verwende am häufigsten Achseneigenschaften.
quelle
Seien Sie streng bei der Angabe von Dimensionen, wenn Sie Aggregationsfunktionen wie min, max, mean, diff, sum, any, all, ... verwenden.
Zum Beispiel die Zeile:
reldiff = diff(a) ./ a(1:end-1)
funktioniert möglicherweise gut, um relative Unterschiede von Elementen in einem Vektor zu berechnen. Wenn der Vektor jedoch zu nur einem Element degeneriert, schlägt die Berechnung fehl:
>> a=rand(1,7); >> diff(a) ./ a(1:end-1) ans = -0.5822 -0.9935 224.2015 0.2708 -0.3328 0.0458 >> a=1; >> diff(a) ./ a(1:end-1) ??? Error using ==> rdivide Matrix dimensions must agree.
Wenn Sie für Ihre Funktionen die richtigen Abmessungen angeben, gibt diese Zeile eine leere 1-mal-0-Matrix zurück, die korrekt ist:
>> diff(a, [], 2) ./ a(1, 1:end-1) ans = Empty matrix: 1-by-0 >>
Gleiches gilt für eine Min-Funktion, die normalerweise Minima über Spalten in einer Matrix berechnet, bis die Matrix nur noch aus einer Zeile besteht. - Dann wird das Minimum über die Zeile zurückgegeben, sofern der Dimensionsparameter nichts anderes angibt, und wahrscheinlich wird Ihre Anwendung beschädigt.
Ich kann Ihnen fast garantieren, dass Sie durch das Festlegen der Dimensionen dieser Aggregationsfunktionen später einige Debugging-Arbeiten sparen.
Zumindest wäre das bei mir der Fall gewesen. :) :)
quelle
a(1:end)
anstelle vona(1:end-1)
diff
Anwendung auf einen Vektor der Größe n hat die Größe n-1.Der Doppelpunktoperator für die Manipulation von Arrays.
@ ScottieT812, erwähnt eines: Abflachen eines Arrays, aber es gibt alle anderen Varianten der Auswahl von Bits eines Arrays:
x=rand(10,10); flattened=x(:); Acolumn=x(:,10); Arow=x(10,:); y=rand(100); firstSix=y(1:6); lastSix=y(end-5:end); alternate=y(1:2:end);
quelle
Um eine Funktion schnell testen zu können, benutze ich Folgendes
nargin
:function result = multiply(a, b) if nargin == 0 %no inputs provided, run using defaults for a and b clc; disp('RUNNING IN TEST MODE') a = 1; b = 2; end result = a*b;
Später füge ich ein Unit-Test-Skript hinzu, um die Funktion für verschiedene Eingabebedingungen zu testen.
quelle
Verwenden von ismember () zum Zusammenführen von Daten, die nach Textkennungen organisiert sind. Nützlich, wenn Sie unterschiedliche Zeiträume analysieren, in denen Einträge, in meinem Fall Firmensymbole, kommen und gehen.
%Merge B into A based on Text identifiers UniverseA = {'A','B','C','D'}; UniverseB = {'A','C','D'}; DataA = [20 40 60 80]; DataB = [30 50 70]; MergeData = NaN(length(UniverseA),2); MergeData(:,1) = DataA; [tf, loc] = ismember(UniverseA, UniverseB); MergeData(tf,2) = DataB(loc(tf)); MergeData = 20 30 40 NaN 60 50 80 70
quelle
Fragen nach dem Warum (nützlich, um mich um 3 Uhr morgens aus einer Matlab-Laufzeit-Fehler-Debugging-Trance herauszuholen ...)
quelle
Ausführen eines Simulink-Modells direkt aus einem Skript (anstatt interaktiv) mit dem
sim
Befehl. Sie können beispielsweise Parameter aus einer Arbeitsbereichsvariablen übernehmen und wiederholtsim
in einer Schleife ausführen , um etwas zu simulieren, während Sie den Parameter variieren, um zu sehen, wie sich das Verhalten ändert, und die Ergebnisse mit beliebigen grafischen Befehlen grafisch darstellen. Viel einfacher als dies interaktiv zu versuchen, und es gibt Ihnen viel mehr Flexibilität als die Simulink "Oszilloskop" -Blöcke bei der Visualisierung der Ergebnisse. (obwohl Sie es nicht verwenden können, um zu sehen, was in Echtzeit passiert, während die Simulation ausgeführt wird)Eine wirklich wichtige Sache zu wissen ist die
DstWorkspace
undSrcWorkspace
Optionen dessimset
Befehls. Diese steuern, wo die Blöcke "To Workspace" und "From Workspace" ihre Ergebnisse abrufen und ablegen.Dstworkspace
Der Standardwert ist der aktuelle Arbeitsbereich (z. B. wenn Siesim
innerhalb einer Funktion aufrufen, werden die Blöcke "To Workspace" als VariablenSrcWorkspace
angezeigt, auf die innerhalb derselben Funktion zugegriffen werden kann). Der Standardwert ist jedoch der Basisarbeitsbereich, und wenn Sie Ihren Anruf ansim
Sie kapseln möchten möchten einstellenSrcWorkspace
,current
damit es eine saubere Schnittstelle zum Bereitstellen / Abrufen von Simulationseingabeparametern und -ausgaben gibt. Zum Beispiel:function Y=run_my_sim(t,input1,params) % runs "my_sim.mdl" % with a From Workspace block referencing I1 as an input signal % and parameters referenced as fields of the "params" structure % and output retrieved from a To Workspace block with name O1. opt = simset('SrcWorkspace','current','DstWorkspace','current'); I1 = struct('time',t,'signals',struct('values',input1,'dimensions',1)); Y = struct; Y.t = sim('my_sim',t,opt); Y.output1 = O1.signals.values;
quelle
Konturdiagramme mit
[c,h]=contour
undclabel(c,h,'fontsize',fontsize)
. Normalerweise benutze ich denfontsize
Parameter, um die Schriftgröße zu reduzieren, damit die Zahlen nicht ineinander laufen. Dies ist ideal, um den Wert von 2D-Funktionen anzuzeigen, ohne mit 3D-Diagrammen herumspielen zu müssen.quelle
Vektorisierung:
function iNeedle = findClosest(hay,needle) %FINDCLOSEST find the indicies of the closest elements in an array. % Given two vectors [A,B], findClosest will find the indicies of the values % in vector A closest to the values in vector B. [hay iOrgHay] = sort(hay(:)'); %#ok must have row vector % Use histogram to find indices of elements in hay closest to elements in % needle. The bins are centered on values in hay, with the edges on the % midpoint between elements. [iNeedle iNeedle] = histc(needle,[-inf hay+[diff(hay)/2 inf]]); %#ok % Reversing the sorting. iNeedle = iOrgHay(iNeedle);
quelle
Verwenden von
persistent
(statischen) Variablen beim Ausführen eines Online-Algorithmus. Dies kann den Code in Bereichen wie dem maschinellen Lernen nach Bayes beschleunigen, in denen das Modell iterativ für die neuen Beispiele trainiert wird. Zum Berechnen der unabhängigen Loglikelihoods berechne ich beispielsweise die Loglikelihood zunächst von Grund auf neu und aktualisiere sie, indem ich diese zuvor berechnete Loglikelihood und die zusätzliche Loglikelihood summiere.Anstatt ein spezielleres Problem des maschinellen Lernens anzugeben, möchte ich einen allgemeinen Online-Mittelungscode angeben, den ich von hier übernommen habe :
function av = runningAverage(x) % The number of values entered so far - declared persistent. persistent n; % The sum of values entered so far - declared persistent. persistent sumOfX; if x == 'reset' % Initialise the persistent variables. n = 0; sumOfX = 0; av = 0; else % A data value has been added. n = n + 1; sumOfX = sumOfX + x; av = sumOfX / n; % Update the running average. end
Die Aufrufe ergeben dann die folgenden Ergebnisse
runningAverage('reset') ans = 0 >> runningAverage(5) ans = 5 >> runningAverage(10) ans = 7.5000 >> runningAverage(3) ans = 6 >> runningAverage('reset') ans = 0 >> runningAverage(8) ans = 8
quelle
persistent
ist gefährlich, da Sie den internen Status nicht direkt festlegen können, was bedeutet, dass Sie nicht richtig testen können. Dies bedeutet auch, dass Sie die Funktion jeweils nur an einem Ort verwenden können. Wenn Sie beispielsweise laufende Durchschnittswerte von zwei getrennten Größen berechnen möchten, müssen Sie die Datei kopieren, um die Zustände zu trennen.Ich bin überrascht, dass, während die Leute den logischen Array-Ansatz der Indizierung eines Arrays erwähnten, niemand den Befehl find erwähnte.
zB wenn x ein NxMxO-Array ist
x (x> 20) generiert ein logisches NxMxO-Array und indiziert damit x (was schlecht sein kann, wenn Sie große Arrays haben und nach einer kleinen Teilmenge suchen
x (find (x> 20)) generiert eine Liste (dh 1xwas auch immer) von Indizes von x, die x> 20 erfüllen, und indiziert x damit. "find" sollte meiner Erfahrung nach mehr verwendet werden als es ist.
Mehr, was ich "Tricks" nennen würde
Sie können Arrays und Zellenarrays vergrößern / anhängen, wenn Sie die benötigte Größe nicht kennen, indem Sie end + 1 verwenden (funktioniert auch mit höheren Dimensionen, solange die Dimensionen des Slice übereinstimmen - so werden Sie müssen x in diesem Fall mit etwas anderem als [] initialisieren). Nicht gut für Zahlen, aber für kleine dynamische Listen von Dingen (oder Zellenarrays), z. B. Parsen von Dateien.
z.B
Ein anderer Gedanke, den viele Leute nicht wissen, ist, dass für Arbeiten an einem dim 1-Array, um das Beispiel fortzusetzen
Das heißt, wenn Sie nur die Mitglieder von x benötigen, müssen Sie sie nicht indizieren.
Dies funktioniert auch mit Zellenarrays, ist jedoch etwas ärgerlich, da das Element beim Gehen immer noch in eine Zelle eingeschlossen ist:
Um an die Elemente zu gelangen, müssen Sie sie abonnieren
Ich kann mich nicht erinnern, ob es einen schöneren Weg gibt, das zu umgehen.
quelle
find
in diesen Situationen ist eine schlechte Idee, da sie redundant und langsamer ist. Persönlich finde ich den logischen Ansatz klarer, weil er auch die zusätzliche Unordnung vermeidet.-Sie können eine Matlab-Verknüpfung zu einer Initialisierungsdatei namens startup.m erstellen. Hier definiere ich Formatierung, Genauigkeit der Ausgabe und Plotparameter für meine Matlab-Sitzung (z. B. verwende ich eine größere Plotachse / Schriftgröße, damit .figs deutlich sichtbar sind, wenn ich sie in Präsentationen einfüge.) Blog-Post von einem der Entwickler darüber http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/ .
-Sie können eine ganze numerische ASCII-Datei mit der Funktion "Laden" laden. Dies ist nicht besonders schnell, erledigt aber die Arbeit für das Prototyping schnell (sollte das nicht das Motto von Matlab sein?)
- Wie bereits erwähnt, sind der Doppelpunktoperator und die Vektorisierung Lebensretter. Schraubenschlaufen.
quelle
Prost - viel Spaß beim Scripting!
quelle
N = sum(I(:));
stattdessen verwenden, arbeitet mit jeder Dimensionalität.numel(x>=3)