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

73

我认为每个人都会同意,MATLAB语言并不美观,也不特别一致。但没关系!我们仍然必须使用它来完成任务。

您有哪些使事情变得更容易的技巧?让我们每个回答提供一个技巧,以便人们可以投票支持他们。此外,请尝试用示例说明您的答案。

31个回答

5

噢,还有反转一个数组

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

6
嗯,我会使用flipud()fliplr()来实现这一点。但是,结合步骤,它更加有用。例如,v(end:-4:1) - Matt
我喜欢我的处理方式,与flipud()/fliplr()不同的是,你不需要知道你是否有一个列向量或行向量。 - Robert Van Hoose
13
可以不使用 length() 函数,改写为: v_reverse = v(end:-1:1); 该语句的意思是将向量 v 倒序排列得到 v_reverse。 - Jonas

4

问“为什么”(在凌晨3点将我从Matlab运行失败的调试状态中唤醒非常有用...)


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

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

“persistent” 是危险的,因为您无法直接设置内部状态,这意味着您无法进行适当的测试。此外,这意味着您一次只能在一个地方使用该函数。例如,如果您想要计算两个不同量的运行平均值,则需要复制文件以分离状态。 - Nzbuu
确实,如果不必要的话,我们应该避免使用它,因为它可能会导致难以注意到的意外问题。在我的问题中,我对一些变量进行了在线修改,从而显著提高了代码的速度。一个人应该谨慎使用它。 - petrichor

3

使用[c,h]=contourclabel(c,h,'fontsize',fontsize)绘制轮廓图。通常我会使用fontsize参数来缩小字体大小,以避免数字相互重叠。这对于查看二维函数的值而不必使用三维图形非常有用。


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

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

需要知道的一个非常重要的事情是 simset 命令中的 DstWorkspaceSrcWorkspace 选项。它们控制“到工作空间”和“从工作空间”块获取和放置其结果的位置。DstWorkspace 默认为当前工作空间(例如,如果您在函数内部调用sim,则“到工作空间”的块将显示为从同一函数内部访问的变量) ,但是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;

2

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

l=x>=3; % l是一个逻辑向量(1或0),用于突出显示数组中符合某个条件的元素。

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

祝您编写脚本愉快!


如果x是3D的话,那么你需要另一个sum()来计算N。我会使用N = sum(I(:));代替,它适用于任何维度。 - catchmeifyoutry
甚至包括 numel(x>=3) - tashuhka

2
-你可以创建一个Matlab快捷方式到一个叫做startup.m的初始化文件。在此,我为我的Matlab会话定义格式、输出精度和绘图参数(例如,我使用较大的绘图轴/字体大小,以便在演示文稿中放置.fig时可以清楚地看到它们)。可以参考开发人员的优秀博客文章了解更多信息:http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/
-你可以使用 "load" 函数加载整个数值ascii文件。这不是特别快,但对于原型设计来说非常快速完成任务(难道这不应该是 Matlab 的座右铭吗?)
-如前所述,冒号运算符和矢量化是救星。忘掉循环。

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(end+1)=4 x = 1 2 3 4
许多人不知道的另一件事是for在任何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
我记不清是否有更好的方法来解决这个问题。

在这种情况下使用 find 是一个不好的主意,因为它是多余的并且速度较慢。个人而言,我发现逻辑方法更清晰,因为它也避免了额外的混乱。 - Nzbuu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接