73

私は、MATLAB言語がきれいではない、または特に一貫していないことに誰もが同意すると思います。でも気にしないで!私たちはまだ物事を成し遂げるためにそれを使わなければなりません。

物事を簡単にするためのあなたの好きなトリックは何ですか?回答ごとに1つ用意して、同意した場合に投票できるようにします。また、例を使って答えを説明してみてください。

4

31 に答える 31

39

組み込みのプロファイラーを使用して、コードのホット パーツがどこにあるかを確認します。

profile on
% some lines of code
profile off
profile viewer

または組み込みを使用して、tic迅速tocなタイミングを取得します。

tic;
% some lines of code
toc;
于 2008-10-14T19:06:58.057 に答える
31

論理配列を使用して、特定の条件を満たす行列の要素を直接抽出します。

x = rand(1,50) .* 100;
xpart = x( x > 20 & x < 35);

xpart には、指定された範囲内にある x の要素のみが含まれます。

于 2008-10-10T17:05:44.217 に答える
28

ヘルプコメントに「SEEALSO」行を追加して、他の機能ドキュメントにすばやくアクセスできるようにします。まず、最初のコメント行として関数の名前をすべて大文字で含める必要があります。通常のコメントヘッダー処理を実行してから、他の関連関数のコンマ区切りリストを使用してSEEALSOを配置します。

function y = transmog(x)
%TRANSMOG Transmogrifies a matrix X using reverse orthogonal eigenvectors
%
% Usage:
%   y = transmog(x)
%
% SEE ALSO
% UNTRANSMOG, TRANSMOG2

コマンドラインで「helptransmog」と入力すると、このコメントヘッダーにすべてのコメントが表示され、リストされている他の関数のコメントヘッダーへのハイパーリンクが表示されます。

于 2008-09-25T12:03:11.727 に答える
23

単一のコロンを使用して行列をベクトルに変換します。

x = rand(4,4);
x(:)
于 2008-09-25T11:57:23.223 に答える
22

ループのベクトル化。これを行う方法はたくさんありますが、コード内のループを探して、それらをベクトル化する方法を確認するのは楽しいことです。ベクトル演算を使用すると、パフォーマンスが驚くほど高速になります。

于 2008-10-14T19:20:28.887 に答える
20

いくつかの理由から、無名関数:

  1. 3x^2+2x+7 のような 1 回限りの使用のためのクイック関数を作成します。(以下のリストを参照) これは、quadやのようなfminbnd関数を引数として取る関数に役立ちます。真の関数とは異なり、サブ関数を含めることができないため、スクリプト (関数ヘッダーで始まらない .m ファイル) でも便利です。
  2. クロージャーの場合-匿名関数は少し制限されていますが、状態を変化させるために割り当てを行う方法がないようです。

.

% 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);
于 2008-12-19T22:08:51.620 に答える
19

Matlab のbsxfunarrayfuncellfun、およびstructfunは非常に興味深いもので、多くの場合、ループを節約します。

M = rand(1000, 1000);
v = rand(1000,    1);
c = bsxfun(@plus, M, v);

たとえば、次のコードは行列 M の各列に列ベクトル v を追加します。

ただし、アプリケーションのパフォーマンスが重要な部分では、これらの関数を簡単な for ループと比較してベンチマークする必要があります。

于 2009-04-08T13:14:36.973 に答える
18

グラフ内の数式の LaTeX モード: 最近のリリース (R2006?) の 1 つでは,'Interpreter','latex'、関数呼び出しの最後に追加の引数を追加すると、LaTeX レンダリングが使用されます。次に例を示します。

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

いつ追加されたかは不明ですが、R2006b の text()、title()、xlabel()、ylabel()、zlabel()、さらには legend() 関数で動作します。使用している構文が曖昧でないことを確認してください (そのため、legend() では、文字列をセル配列として指定する必要があります)。

于 2008-12-19T21:28:07.630 に答える
17

xlimとylimを使用して垂直線と水平線を描画します。例:

  1. y=10で水平線を引きます。

    line(xlim, [10 10])

  2. x=5で垂直線を引きます。

    line([5 5], ylim)

于 2009-10-23T06:55:54.550 に答える
16

簡単な例を次に示します。

カンマ区切りのリスト構文は、関数呼び出しを作成するのに非常に便利です。

% Build a list of args, like so:
args = {'a', 1, 'b', 2};
% Then expand this into arguments:
output = func(args{:})
于 2008-09-25T08:21:34.207 に答える
11

時々役立つ、自明ではない関数の束を次に示します。

  • mfilename(現在実行中の MATLAB スクリプトの名前を返します)
  • dbstack(matlab 関数スタックの名前と行番号にアクセスできます)
  • keyboard(実行を停止し、デバッグ プロンプトに制御を渡します。これが、デバッグ プロンプトに K がある理由です。K>>
  • dbstop error(エラーが発生した行で停止したデバッグ モードに自動的に移行します)
于 2008-12-19T21:25:41.070 に答える
10

MatlabからのJavaコードの呼び出し

于 2008-09-25T08:21:39.357 に答える
10

多くの理由から、関数ハンドルを使用するのが好きです。1 つは、これらは私が MATLAB で見つけたポインターに最も近いものであるため、オブジェクトの参照のような動作を作成できます。それらを使ってできる、すてきな (そしてもっと簡単な) こともいくつかあります。たとえば、switch ステートメントを次のように置き換えます。

switch number,
  case 1,
    outargs = fcn1(inargs);
  case 2,
    outargs = fcn2(inargs);
  ...
end
%
%can be turned into
%
fcnArray = {@fcn1, @fcn2, ...};
outargs = fcnArray{number}(inargs);

そんな些細なことがカッコイイと思います。

于 2009-01-08T05:25:37.707 に答える
10

nargin を使用してオプションの引数のデフォルト値を設定し、nargout を使用してオプションの出力引数を設定します。簡単な例

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
于 2008-09-28T22:13:05.220 に答える
5

min、max、mean、diff、sum、any、all、...などの集計関数を使用する場合は、ディメンションの指定を厳密に行ってください。

たとえば、次の行です。

reldiff = diff(a) ./ a(1:end-1)

ベクトル内の要素の相対的な差を計算するのにうまくいくかもしれませんが、ベクトルが1つの要素だけに縮退した場合、計算は失敗します。

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

関数に正しい次元を指定すると、この行は空の1行0列の行列を返します。これは正しいです。

>> diff(a, [], 2) ./ a(1, 1:end-1)

ans =

   Empty matrix: 1-by-0

>> 

行列が1行のみで構成されるまで、通常は行列の列の最小値を計算するmin関数についても同じことが言えます。-次に、ディメンションパラメータで特に明記されていない限り、行全体で最小値が返され、アプリケーションが破損する可能性があります。

その結果、これらの集計関数のディメンションを設定すると、後でデバッグ作業をかなり節約できることをほぼ保証できます。

少なくとも私にとってはそうだったでしょう。:)

于 2009-04-08T13:40:54.740 に答える
5

自動 for ループ用の cellfun と arrayfun。

于 2008-09-25T12:34:15.410 に答える
5

代入の左側の条件付き引数:

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);
于 2008-12-19T22:14:20.143 に答える
5

ああ、配列を逆にする

v = 1:10;
v_reverse = v(length(v):-1:1);
于 2008-10-14T19:14:29.540 に答える
5

関数をすばやくテストできるようにするために、次の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;

後で、単体テスト スクリプトを追加して、さまざまな入力条件で関数をテストします。

于 2010-10-14T09:19:22.680 に答える
5

配列操作用のコロン演算子。

@ ScottieT812 は、1 つ言及しています: 配列をフラット化しますが、配列のビットを選択する他のすべてのバリエーションがあります。


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);
于 2008-09-26T10:50:22.097 に答える
4

ismember() を使用して、テキスト識別子によって編成されたデータをマージします。エントリ (私の場合は会社のシンボル) が行き来するさまざまな期間を分析する場合に役立ちます。

%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
于 2008-10-14T19:11:26.800 に答える
4

「なぜ」を尋ねる (午前 3 時の Matlab ランタイム失敗デバッグ トランスから私を不快にさせるのに役立ちます...)

于 2011-04-28T04:13:31.677 に答える
3

コマンドを使用して、(対話的にではなく)スクリプトから直接Simulinkモデルを実行しsimます。ワークスペース変数からパラメーターを取得し、ループで繰り返し実行simしてパラメーターを変更しながら何かをシミュレートし、動作がどのように変化するかを確認し、任意のグラフィカルコマンドで結果をグラフ化するなどの操作を実行できます。これをインタラクティブに実行するよりもはるかに簡単で、結果を視覚化するときにSimulinkの「オシロスコープ」ブロックよりもはるかに柔軟性があります。(ただし、シミュレーションの実行中にリアルタイムで何が起こっているかを確認するために使用することはできません)

知っておくべき本当に重要なことは、コマンドのDstWorkspaceSrcWorkspaceオプションです。simsetこれらは、「ToWorkspace」ブロックと「FromWorkspace」ブロックが結果を取得および配置する場所を制御します。Dstworkspaceデフォルトは現在のワークスペースです(たとえばsim、関数内から「To Workspace」ブロックを呼び出すと、同じ関数内からアクセスできる変数として表示されます)が、SrcWorkspaceデフォルトはベースワークスペースになり、呼び出しをカプセル化するsim場合はシミュレーションの入力パラメータと出力を提供/取得するためのクリーンなインターフェイスがあるように設定SrcWorkspaceする必要があります。current例えば:

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;
于 2008-12-19T21:41:11.350 に答える
3

[c,h]=contourとを使用した等高線図clabel(c,h,'fontsize',fontsize)。私は通常、このfontsizeパラメーターを使用してフォントサイズを小さくし、数値が互いにぶつからないようにします。これは、3Dグラフをいじくり回すことなく、2D関数の値を表示するのに最適です。

于 2008-12-19T21:45:37.923 に答える
3

persistentオンライン アルゴリズムの実行時に (静的) 変数を使用する。モデルが新しいサンプルに対して反復的にトレーニングされるベイジアン機械学習などの分野でコードを高速化する可能性があります。たとえば、独立した対数尤度を計算するために、最初から対数尤度を計算し、この以前に計算された対数尤度と追加の対数尤度を合計して更新します。

より専門的な機械学習の問題を与える代わりに、ここから取った一般的なオンライン平均化コードを与えましょう:

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

次に、呼び出しにより次の結果が得られます

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
于 2011-06-27T11:27:11.257 に答える
3

ベクトル化:

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);
于 2008-11-12T15:43:44.387 に答える
2

これが私が頻繁に使用するものです:

% useful abbreviations

flat=@(x) x(:);

% print basic statistics
stats=@(x) sprintf('mean +/- s.d. \t= %f +/- %f\nmin, max \t\t= %f, %f\nmedian, mode \t= %f, %f', ...
    mean(flat(x)), std(flat(x)), min(flat(x)), max(flat(x)), median(flat(x)), mode(flat(x)) );

nrows=@(x) size(x,1);
ncols=@(x) size(x,2);
nslices=@(x) size(x,3);

% this is just like ndims except it returns 0 for an empty matrix and
% ignores dimensions of size 0.
ndim=@(x) length(find(size(x)));

これらの略語は、画像の小さな領域のピクセル値の平均偏差と標準偏差を見つけるのに役立ちます。次のロジックを使用します。

phantomData = phantom();

stats( phantomData(50:80, 50:80) )

タイトルに画像のサイズを入れたい場合はどうすればよいですか?

imagesc( phantomData );

title( sprintf('The image size is %d by %d by %d.', nrows(phantomData), ncols(phantomData), nslices(phantomData)) )

于 2011-07-25T13:30:42.140 に答える
2

配列にインデックスを付けるという論理配列アプローチについて言及した人がいる一方で、find コマンドについて言及した人が誰もいなかったことに驚いています。

たとえば、x が NxMxO 配列の場合

x(x>20) は、NxMxO 論理配列を生成し、それを使用して x のインデックスを作成することで機能します (大きな配列があり、小さなサブセットを探している場合、これは不適切な場合があります)。

x(find(x>20)) は、x>20 を満たす x のインデックスのリスト (つまり、1xwhatever) を生成し、それによって x にインデックスを付けることによって機能します。私の経験では、「find」はそれ以上に使用する必要があります。

私が「トリック」と呼ぶもの

必要なサイズがわからない場合は、 end + 1 を使用して、配列とセル配列に拡張/追加できます (スライスの次元が一致する限り、より高い次元でも機能します。その場合、x を [] 以外に初期化する必要があります)。数値には適していませんが、ファイルの解析など、物事 (またはセル配列) の小さな動的リストには適していません。

例えば

>> x=[1,2,3]
x = 1 2 3
>> x(終わり+1)=4
x = 1 2 3 4

多くの人が知らないもう1つの考えは、 for が任意のdim 1配列で動作することです。そのため、例を続ける

>> n = x の場合;disp(n);end
     1
     2
     3
     4

つまり、必要なのが x のメンバーだけである場合、それらにインデックスを付ける必要はありません。

これはセル配列でも機能しますが、要素がセルにラップされているため、少し面倒です。

>> el = {1,2,3,4} の場合;disp(el);end
    [1]
    [2]
    [3]
    [4]

したがって、要素を取得するには、それらに添字を付ける必要があります

>> el = {1,2,3,4} の場合;disp(el{1});end
     1
     2
     3
     4

それを回避するより良い方法があるかどうかは思い出せません。

于 2009-04-08T13:56:33.970 に答える
2

x=repmat([1:10],3,1); % たとえば、x はデータの配列の例です

l=x>=3; % l は、特定の条件を満たす配列内の要素を強調表示するための論理ベクトル (1/0) です。

N=sum(sum(l));% N は、その条件を満たす要素の数です。

乾杯 -- 楽しいスクリプティング!

于 2010-12-22T02:33:52.537 に答える