你最喜欢的MATLAB / Octave编程技巧是什么?

时间:2008-09-25 08:19:31

标签: matlab octave

我认为每个人都会同意MATLAB语言不漂亮或特别一致。但是不要紧!我们仍然需要用它来完成任务。

你最喜欢的技巧是什么?我们每个答案都有一个,所以如果他们同意,人们可以投票。另外,尝试用一个例子说明你的答案。

31 个答案:

答案 0 :(得分:39)

使用内置的分析器查看我的代码的热门部分:

profile on
% some lines of code
profile off
profile viewer

或仅使用内置的tictoc来获得快速时间:

tic;
% some lines of code
toc;

答案 1 :(得分:31)

使用逻辑数组直接提取满足特定条件的矩阵元素:

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

现在xpart只包含那些位于指定范围内的x元素。

答案 2 :(得分:28)

通过在帮助评论中添加“另请参阅”行,可以快速访问其他功能文档。首先,您必须在所有大写字母中包含函数的名称作为第一个注释行。做你平常的评论标题,然后再看看其他相关函数的逗号分隔列表。

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

当您在命令行中键入“help transmog”时,您将看到此注释标题中的所有注释,以及指向列出的其他函数的注释标题的超链接。

答案 3 :(得分:23)

使用单个冒号将矩阵转换为矢量。

x = rand(4,4);
x(:)

答案 4 :(得分:22)

Vectorizing loops。有很多方法可以做到这一点,在代码中查找循环并查看它们如何被矢量化是很有趣的。使用矢量运算,性能惊人地快了!

答案 5 :(得分:20)

匿名函数,原因如下:

  1. 为一次性使用提供快速功能,例如3x ^ 2 + 2x + 7。 (参见下面的清单)这对于将函数作为参数的quadfminbnd等函数很有用。它在脚本中也很方便(.m文件不以函数头开头),因为与真正的函数不同,你不能包含子函数。
  2. for closures - 虽然匿名函数有一点限制,因为似乎没有办法在其中赋值以改变状态。
  3. % 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);
    

答案 6 :(得分:19)

Matlab的bsxfunarrayfuncellfunstructfun非常有趣,通常可以保存循环。

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

例如,此代码将列向量v添加到矩阵M的每一列。

尽管在应用程序的性能关键部分中,您应该对这些函数进行基准测试,而不是简单的for循环,因为通常循环仍然更快。

答案 7 :(得分:18)

LaTeX mode for formulas in graphs:在最近的一个版本(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');

不确定何时添加它,但它适用于文本(),title(),xlabel(),ylabel(),zlabel()甚至legend()函数中的R2006b。只需确保您使用的语法不明确(因此使用legend()时,您需要将字符串指定为单元格数组。)

答案 8 :(得分:17)

使用xlim和ylim绘制垂直和水平线。例子:

  1. 在y = 10处绘制一条水平线:

    line(xlim, [10 10])

  2. 在x = 5处绘制垂直线:

    line([5 5], ylim)

答案 9 :(得分:16)

这是一个简单的例子:

我发现逗号分隔列表语法对于构建函数调用非常有用:

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

答案 10 :(得分:11)

以下是一些非常有用的功能:

  • mfilename(返回当前运行的MATLAB脚本的名称)
  • dbstack(允许您访问matlab函数堆栈的名称和行号)
  • keyboard(停止执行并将控制权交给调试提示;这就是为什么在调试提示符中有一个K K>>
  • dbstop error(自动将您置于调试模式,在触发错误的行停止)

答案 11 :(得分:10)

从Matlab调用Java代码

答案 12 :(得分:10)

我喜欢使用函数句柄有很多原因。首先,它们是我在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);

我认为像这样的小事很酷。

答案 13 :(得分: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

答案 14 :(得分:5)

哦,并反转数组

v = 1:10;
v_reverse = v(length(v):-1:1);

答案 15 :(得分: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);

答案 16 :(得分:5)

用于操作数组的冒号运算符。

@ ScottieT812,提到一个:展平一个数组,但是还有所有其他选择数组位的变体:


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

答案 17 :(得分:5)

了解你的axis properties!你可以设置各种各样的东西来调整默认的绘图属性来做你想做的事情:

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

(例如,将fontsize设置为8pt,所有新行的线条样式都是实线,宽度为0.3pt,xtick指向[1 3 5 7 9])

Linefigure属性也很有用,但我发现自己最常使用轴属性。

答案 18 :(得分:5)

cellfun和arrayfun用于自动化for循环。

答案 19 :(得分:5)

在使用聚合函数(如min,max,mean,diff,sum,any,all,...)时严格指定尺寸。

例如,行:

reldiff = diff(a) ./ a(1:end-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

>> 

对于通常计算矩阵上的列的最小值的最小函数也是如此,直到矩阵仅由一行组成。 - 然后它将返回行的最小值,除非维度参数另有说明,并且可能会破坏您的应用程序。

我几乎可以向您保证,因此设置这些聚合函数的尺寸将为您节省大量的调试工作。

至少对我来说就是这种情况。 :)

答案 20 :(得分: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;

稍后,我添加了一个单元测试脚本来测试不同输入条件的函数。

答案 21 :(得分: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

答案 22 :(得分:4)

问'为什么'(对于让我摆脱Matlab运行时有用 - 在凌晨3点失败调试恍惚......)

答案 23 :(得分:3)

运行在线算法时使用persistent(静态)变量。它可以加速贝叶斯机器学习等领域的代码,其中模型被迭代地训练用于新样本。例如,为了计算独立的对数似然,我首先从头开始计算对数似然,并通过对先前计算的对数似然和附加对数似然进行求和来更新它。

不要给出更专业的机器学习问题,让我给出一般的在线平均代码from here

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

答案 24 :(得分:3)

使用sim命令直接从脚本(而不是交互式)执行Simulink模型。您可以执行以下操作:例如从工作空间变量中获取参数,并在循环中重复运行sim以模拟某些内容,同时更改参数以查看行为如何更改,并使用您喜欢的任何图形命令对结果进行绘图。比尝试以交互方式执行此操作要容易得多,并且在可视化结果时,它比Simulink“示波器”块具有更大的灵活性。 (虽然在模拟运行时你无法使用它来实时查看正在发生的事情)

要知道的一件非常重要的事情是simset命令的DstWorkspaceSrcWorkspace选项。这些控制“To Workspace”和“From Workspace”块获取并放置其结果的位置。 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;

答案 25 :(得分:3)

包含[c,h]=contourclabel(c,h,'fontsize',fontsize)的轮廓图。我通常使用fontsize参数来减小字体大小,这样数字就不会相互碰撞。这非常适合查看二维函数的值,而不必使用三维图形。

答案 26 :(得分: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);

答案 27 :(得分:2)

- 您可以创建一个名为startup.m的初始化文件的Matlab快捷方式。在这里,我定义了Matlab会话的格式,输出精度和绘图参数(例如,我使用更大的绘图轴/字体大小,以便在我将它们放入演示文稿时可以清楚地看到.fig。)看到一个好的来自其中一位开发者的博客文章http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/

- 您可以使用“加载”功能加载整个数字ascii文件。这不是特别快,但是可以快速完成工作原型(不应该是Matlab的座右铭吗?)

- 如上所述,冒号运算符和矢量化是救生员。螺旋环。

答案 28 :(得分:2)

我很惊讶当人们提到索引数组的逻辑数组方法时,没有人提到find命令。

e.g。如果x是NxMxO数组

x(x> 20)通过生成NxMxO逻辑数组并使用它来索引x来工作(如果你有大型数组并且正在寻找一个小子集,这可能会很糟糕

x(find(x> 20))通过生成满足x> 20的x的索引的列表(即1xwhatever)并且通过它索引x来工作。根据我的经验,“发现”应该比它更多地使用。

更多我称之为'技巧'

如果你不知道你需要的大小,你可以使用end + 1来增长/附加到数组和单元格数组(只要切片的尺寸匹配,也可以使用更高的尺寸 - 所以在这种情况下,你必须将x初始化为除[]之外的其他东西。不适用于数字,但适用于动态的小动态列表(或单元阵列),例如:解析文件。

e.g。

>> x=[1,2,3]
x =  1     2     3
>> x(end+1)=4
x =  1     2     3     4

另一种认为很多人不知道的是,对于任何昏暗的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

我不记得是否有更好的方法。

答案 29 :(得分:2)

  

X = repmat([1:10],3,1); %,x是一个示例数据数组

     

1 = X&GT; = 3; %l是一个逻辑向量(1s / 0s),用于突出显示满足特定条件的数组中的那些元素。

     

N = sum(sum(l));%N是满足给定条件的元素数。

欢呼 - 快乐的脚本!

答案 30 :(得分: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)));

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

如果我想将图片的大小放在标题中怎么办?

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

imagesc( phantomData );