首页 文章

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

提问于
浏览
73

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

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

30 回答

  • 10

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

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

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

  • 16

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

    profile on
    % some lines of code
    profile off
    profile viewer
    

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

    tic;
    % some lines of code
    toc;
    
  • 23

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

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

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

  • 28

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

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

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

  • 5

    匿名函数,原因如下:

    • 为一次性使用提供快速功能,如3x ^ 2 2x 7.(参见下面的清单)这对于将函数作为参数的函数(如 quadfminbnd )非常有用 . 它是以函数头开头的,因为与真函数不同,你不能包含子函数 .

    • for 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);
    
  • 10

    Matlab的bsxfunarrayfuncellfunstructfun非常有趣并经常保存循环 .

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

    例如,该代码将列向量v添加到矩阵M的每列 .

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

  • 2

    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()时,您需要将字符串指定为单元格数组) .

  • 17

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

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

    line(xlim, [10 10])

    • 在x = 5处绘制垂直线:

    line([5 5], ylim)

  • 31

    这是一个简单的例子:

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

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

    这里有一堆非常明显的功能,不时有用:

    • mfilename (返回当前运行的MATLAB脚本的名称)

    • dbstack (允许您访问matlab函数堆栈的名称和行号)

    • keyboard (停止执行并将控制权交给调试提示;这就是调试提示中有一个K的原因 K>>

    • dbstop error (自动使您进入调试模式,停止在触发错误的行)

  • 4

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

    我只是认为像这样的小事很酷 .

  • 5

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

    从Matlab调用Java代码

  • 3

    cellfun和arrayfun用于自动for循环 .

  • 11

    哦,并反转一个阵列

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

    赋值左侧的条件参数:

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

    知道你的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属性也很有用,但我发现自己最常使用轴属性 .

  • 3

    在使用聚合函数时要严格指定维度,例如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

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

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

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

  • 5

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

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

  • 2

    使用 sim 命令直接从脚本(而不是交互式)执行Simulink模型 . 您可以执行以下操作:例如从工作空间变量中获取参数,并在循环中重复运行 sim 以模拟某些内容,同时更改参数以查看行为如何更改,并使用您喜欢的任何图形命令对结果进行绘图 . 比尝试以交互方式执行此操作要容易得多,并且在可视化结果时,它比Simulink "oscilloscope"块提供了更多的灵活性 . (虽然你可以在模拟运行时实时进行't use it to see what')

    一个非常重要的事情是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;
    
  • 5

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

  • 4

    矢量:

    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

    运行在线算法时使用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
    
  • 19

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

    例如如果x是NxMxO数组

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

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

    更多我称之为'技巧'的东西

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

    例如

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

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

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

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

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

  • 2

    x = repmat([1:10],3,1); %,x是数据的示例数组l = x> = 3; %l是一个逻辑向量(1s / 0s),用于突出显示满足特定条件的数组中的那些元素 . N = sum(sum(l));%N是满足给定条件的元素数 .

    欢呼 - 快乐的脚本!

相关问题