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

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

你最喜欢什么让事情变得更容易的技巧? 让我们每个答案有一个,所以如果他们同意,人们可以投票。 另外,试着用一个例子来说明你的答案。

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

profile on % some lines of code profile off profile viewer 

或者只是使用内置的tictoc来获得快速的定时:

 tic; % some lines of code toc; 

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

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

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

通过在帮助注释中添加“另请参见”行,提供对其他function文档的快速访问。 首先,必须在所有大写中包含该函数的名称作为第一个注释行。 做你平常的评论标题的东西,然后把另一个逗号分隔列表的其他相关的function。

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

当你在命令行input“help transmog”的时候,你会看到这个注释标题中的所有注释,超链接到列出的其他function的注释标题。

使用单个冒号将matrix转换为vector。

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

向量化循环 。 有很多方法可以做到这一点,并且在代码中查找循环并查看它们如何被vector化是有趣的。 vector操作的性能惊人地快!

匿名function,原因如下:

  1. 做一次性用途的快速function,如3x ^ 2 + 2x + 7。 (见下面的清单)这对于像函数作为参数的quadfminbnd这样的函数是很有用的。 脚本(.m文件不是以函数头开头)也很方便,因为与真正的函数不同,你不能包含子函数。
  2. 对于闭包来说 – 尽pipe匿名函数有一点限制,因为似乎没有办法在它们之间赋值来改变状态。

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

Matlab的bsxfun , arrayfun , cellfun和structfun是相当有趣的,经常保存一个循环。

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

例如,这个代码将列vectorv添加到matrixM的每一列。

虽然在应用程序的性能关键部分,您应该将这些函数与简单的for循环进行基准testing,因为经常循环更快。

LaTeX模式用于图表中的公式 :在最近的一个版本(R2006?)中,'Interpreter','latex'在函数调用结束时添加额外的参数,'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'); 

不知道什么时候添加它,但它在文本(),标题(),xlabel(),ylabel(),zlabel(),甚至legend()函数R2006b。 只要确保你使用的语法不是不明确的(所以在legend()中你需要把string指定为一个单元格数组)。

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

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

    line(xlim, [10 10])

  2. 在x = 5处画垂直线:

    line([5 5], ylim)

这里有一个简单的例子:

我发现逗号分隔列表语法非常有用的build设函数调用:

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

下面是一些非常有用的非常有用的函数:

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

我喜欢使用function手柄有很多原因。 首先,他们是我在MATLAB中find的最接近的指针,所以你可以为对象创build类似引用的行为。 还有一些你可以用它们完成的简单的事情。 例如,replace一个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); 

我只是觉得这样的小事很酷。

使用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 

从Matlab调用Java代码

cellfun和arrayfun自动循环。

哦,并倒序一个数组

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

在作业左侧的条件论据:

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

知道你的轴属性 ! 有各种各样的东西,你可以设置来调整默认绘图属性做你想做的事情:

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

(例如,将字体大小设置为8pt,所有新行的线型为实心,宽度为0.3pt,xtick点为[1 3 5 7 9])

线条和graphics属性也很有用,但是我发现自己最擅长使用轴属性。

在使用聚合函数(如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乘0matrix,这是正确的:

 >> diff(a, [], 2) ./ a(1, 1:end-1) ans = Empty matrix: 1-by-0 >> 

对于通常计算matrix上的列的最小值的最小函数也是如此,直到matrix只包含一行。 – 然后它会返回最小的行,除非尺寸参数另有说明,并可能会破坏你的应用程序。

我几乎可以保证,因此设置这些聚合函数的维度将在以后节省相当多的debugging工作。

至less对我来说是这样的。 🙂

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

@ ScottieT812提到:平坦化一个数组,但是还有select数组的位的所有其他变体:

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

为了能够快速testing一个函数,我使用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; 

稍后,我添加一个unit testing脚本来testing不同input条件的函数。

使用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 

询问“为什么”(对于在Matlab运行时出现的问题非常有用 – 在凌晨3点失败的debugging恍惚…)

使用sim命令直接从脚本(而不是交互式)执行Simulink模型。 你可以做一些事情,比如从工作区variables中获取参数,在一个循环中反复运行sim来模拟一些事情,同时改变参数以查看行为是如何改变的,并用你喜欢的任何graphics命令来绘制结果。 比试图以交互方式做这件事要容易得多,而且在可视化结果时,它比Simulink“示波器”模块更具灵活性。 (尽pipe模拟运行时不能用它来实时查看发生了什么)

要知道一个非常重要的事情是simset命令的DstWorkspaceSrcWorkspace选项。 这些控制“工作区”和“从工作区”块获取和放置结果的位置。 Dstworkspace默认为当前工作空间(例如,如果从函数内部调用sim ,“To Workspace”块将显示为在同一个函数内可访问的variables),但是SrcWorkspace默认为基本工作空间,并且如果要将呼叫封装到sim你将要设置SrcWorkspacecurrent所以有一个干净的界面来提供/检索模拟input参数和输出。 例如:

 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; Yt = sim('my_sim',t,opt); Y.output1 = O1.signals.values; 

[c,h]=contourclabel(c,h,'fontsize',fontsize)等高线图。 我通常使用fontsize参数来减小字体大小,这样数字就不会碰到对方。 这非常适合查看二维函数的价值,而无需使用三维graphics。

vector:

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

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

我不是给出一个更专门的机器学习问题,而是给出一个我从这里取得的一般的在线平均代码:

 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 

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

例如,如果x是一个NxMxO数组

x(x> 20)通过生成一个NxMxO逻辑数组并使用它来索引x(如果您有大数组并且正在寻找一个小子集

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

更多我所说的“技巧”

如果你不知道你需要的大小,你可以通过使用end + 1来增长/附加到数组和单元arrays(只要片的尺寸匹配,就可以使用更高的维数)在这种情况下,必须将x初始化为[]以外的内容)。 对数值不好,但对于小的dynamic列表(或单元arrays),例如parsing文件。

例如

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

另外想想很多人不知道的是,对于任何暗淡的arrays作品,所以继续这样的例子

 >>对于n = x; disp(n);结束
      1
      2
      3
      4

这意味着如果你所需要的只是x的成员,你不需要索引它们。

这也适用于单元arrays,但它有点烦人,因为它走它们的元素仍然包裹在一个单元格中:

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

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

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

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

如前所述,冒号操作符和向量化是救星。 螺丝圈。

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

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

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

欢呼声 – 快乐的脚本!