web-dev-qa-db-ja.com

好きなMATLAB / Octaveプログラミングのトリックは何ですか?

MATLAB言語がきれいではない、または特に一貫性がないことに誰もが同意すると思います。でも気にしないで!物事を成し遂げるためにそれを使用する必要があります。

物事を簡単にするためのお気に入りのトリックは何ですか?回答ごとに1つ用意して、人々が同意すれば投票できるようにします。また、例を使って答えを説明してください。

73
Matt

組み込みのプロファイラーを使用して、コードの重要な部分を確認します。

profile on
% some lines of code
profile off
profile viewer

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

tic;
% some lines of code
toc;
39
Jason Sundram

論理配列を使用して、特定の条件を満たすマトリックスの要素を直接抽出します。

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

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

31
sundar

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

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

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

28
Scottie T

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

x = Rand(4,4);
x(:)
23
Scottie T

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

22
Jason Sundram

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

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

% 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);
20
Jason S

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

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

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

ただし、アプリケーションのパフォーマンスが重要な部分では、多くの場合ループが依然として高速であるため、これらの関数と些細なforループのベンチマークを行う必要があります。

19
ymihere

グラフの数式のLaTeXモード :最近のリリースの1つ(R2006?)では、追加の引数,'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()では、文字列をセル配列として指定する必要があります)。

18
Jason S

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

  1. Y = 10に水平線を描画します。

    line(xlim, [10 10])

  2. X = 5に垂直線を描画します。

    line([5 5], ylim)

17
Samil

以下に簡単な例を示します。

コンマ区切りリスト構文は、関数呼び出しを作成するのに非常に役立ちます。

% Build a list of args, like so:
args = {'a', 1, 'b', 2};
% Then expand this into arguments:
output = func(args{:})
16
Matt

以下は、時々役立つ便利な関数です。

  • mfilename(現在実行中のMATLABスクリプトの名前を返します)
  • dbstack(matlab関数スタックの名前と行番号にアクセスできます)
  • keyboard(実行を停止し、デバッグプロンプトに制御を渡します。これが、デバッグプロンプトにKがある理由ですK>>
  • dbstop error(エラーを引き起こす行で停止したデバッグモードに自動的に移動します)
11
Jason S

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

10
Rorick

私は多くの理由で関数ハンドルを使うのが好きです。 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);

私はそのようなささいなことはクールだと思います。

10
gnovice

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
10
Azim

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

後で、さまざまな入力条件について関数をテストするユニットテストスクリプトを追加します。

5
Samil

自動化されたforループ用のcellfunおよびarrayfun。

5
KennyMorton

割り当ての左側の条件引数:

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);
5
Jason S

配列を操作するためのコロン演算子。

@ 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);
5
Ian Hopkinson

ああ、そして配列を逆にします

v = 1:10;
v_reverse = v(length(v):-1:1);
5
R. Van Hoose

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関数にも同じことが言えます。 -次に、dimensionパラメーターで特に指定されていない限り、行の最小値が返され、おそらくアプリケーションが壊れます。

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

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

5
ymihere

軸のプロパティ !必要な処理を行うために、デフォルトのプロットプロパティを微調整するように設定できるすべての種類があります。

set(gca,'fontsize',8,'linestyleorder','-','linewidth',0.3,'xtick',1:2:9);

(例として、フォントサイズを8ptに設定し、すべての新しい行の線スタイルをすべて実線で幅を0.3ptに設定し、xtickポイントを[1 3 5 7 9]に設定します)

Line および figure プロパティも便利ですが、軸プロパティを最もよく使用しています。

5
Jason S

「なぜ」と尋ねる(午前3時にMatlabのランタイムフェールデバッグトランスから耳障りになるのに役立ちます...)

4
David Cuccia

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

%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
4
R. Van Hoose

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

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

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;
3
Jason S

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

3
Jason S

ベクトル化:

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);
3
user36927

オンラインアルゴリズムの実行時に 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
3
petrichor

人々が配列にインデックスを付ける論理配列アプローチについて言及しているのに、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(end + 1)= 4 
 x = 1 2 3 4 

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

 >> for n = x; disp(n); end 
 1 
 2 
 3 
 4 

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

これはセル配列でも動作しますが、それらを歩くときに要素がまだセルにラップされているため、少し面倒です:

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

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

 >> for el = {1,2,3,4}; disp(el {1}); end 
 1 
 2 
 3 
 4 

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

2
simon

-startup.mという初期化ファイルへのMatlabショートカットを作成できます。ここで、Matlabセッションのフォーマット、出力の精度、およびプロットパラメーターを定義します(たとえば、プレゼンテーションに配置するときに.figがはっきりと見えるように、より大きなプロット軸/フォントサイズを使用します)。開発者の1人からのブログ投稿 http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/ .

-「ロード」機能を使用して、数値ASCIIファイル全体をロードできます。これは特に高速ではありませんが、プロトタイピングの仕事を迅速に完了させます(Matlabのモットーではないでしょうか?)

-前述のように、コロン演算子とベクトル化はライフセーバーです。ねじループ。

2
temp2290

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

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

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

乾杯-ハッピースクリプト!

2
Y.T.

私が頻繁に使用するものは次のとおりです。

_% 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)));
_ </ code>

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

phantomData = phantom();

_stats( phantomData(50:80, 50:80) )
_ </ code>

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

imagesc( phantomData );

_title( sprintf('The image size is %d by %d by %d.', nrows(phantomData), ncols(phantomData), nslices(phantomData)) )
_ </ code>
2
user244795