Какой ваш любимый трюк программирования MATLAB/Octave?

Думаю, все согласятся с тем, что язык MATLAB не очень хорош или особенно последователен. Но не бери в голову! Мы все еще должны использовать его, чтобы все было сделано.

Каковы ваши любимые трюки для облегчения дела? Пусть есть один ответ, чтобы люди могли проголосовать за них, если они согласны. Также попробуйте проиллюстрировать свой ответ на примере.

Ответ 1

Используя встроенный профилировщик, чтобы узнать, где находятся горячие части моего кода:

profile on
% some lines of code
profile off
profile viewer

или просто используя встроенные tic и toc, чтобы получить быстрые тайминги:

tic;
% some lines of code
toc;

Ответ 2

Непосредственное извлечение элементов матрицы, удовлетворяющих определенному условию, с использованием логических массивов:

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

Теперь xpart содержит только те элементы из x, которые лежат в указанном диапазоне.

Ответ 3

Обеспечьте быстрый доступ к другой документации по функциям, добавив строку "СМОТРИТЕ ТАКЖЕ" в комментарии справки. Во-первых, вы должны указать имя функции во всех кепках в качестве первой строки комментария. Сделайте свой обычный заголовок комментария, затем добавьте SEE ALSO с разделенным запятыми списком других связанных функций.

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

Когда вы вводите "help transformog" в командной строке, вы увидите все комментарии в этом заголовке комментария, с гиперссылками к заголовкам комментариев для других перечисленных функций.

Ответ 4

Поверните матрицу в вектор, используя один двоеточие.

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

Ответ 5

Векторизация циклов. Есть много способов сделать это, и интересно посмотреть на циклы в коде и посмотреть, как они могут быть векторизованы. Эффективность поразительно быстрее с векторными операциями!

Ответ 6

Анонимные функции по нескольким причинам:

  • чтобы сделать быструю функцию для одноразовых применений, например 3x ^ 2 + 2x + 7. (см. список ниже). Это полезно для таких функций, как quad и fminbnd, которые принимают функции в качестве аргументов. Это также удобно в сценариях (файлы .m, которые не начинаются с заголовка функции), поскольку в отличие от истинных функций вы не можете включать подфункции.
  • для закрытия - хотя анонимные функции немного ограничены, поскольку, похоже, не существует способа иметь в них назначение мутировать состояние.

.

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

Ответ 7

Matlab bsxfun, arrayfun, cellfun, и structfun довольно интересны и часто сохраняйте цикл.

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

Этот код, например, добавляет вектор-столбец v к каждому столбцу матрицы M.

Хотя в критичных для производительности частях приложения вы должны сравнивать эти функции с тривиальным циклом for, потому что часто петли все еще быстрее.

Ответ 8

Режим LaTeX для формул в графах: В одном из последних выпусков (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(). Просто убедитесь, что используемый вами синтаксис не является двусмысленным (поэтому с легендой() вам нужно указать строки как массивы ячеек).

Ответ 9

Использование xlim и ylim для рисования вертикальных и горизонтальных линий. Примеры:

  • Нарисуйте горизонтальную линию при y = 10:

    line(xlim, [10 10])

  • Нарисуйте вертикальную линию при x = 5:

    line([5 5], ylim)

Ответ 10

Вот пример:

Я считаю, что синтаксис списка с разделителями-запятыми весьма полезен для построения вызовов функций:

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

Ответ 11

Здесь куча неочевидных функций, которые время от времени полезны:

  • mfilename (возвращает имя текущего запущенного MATLAB script)
  • dbstack (дает вам доступ к именам и номерам строк стека функций Matlab)
  • keyboard (останавливает выполнение и дает возможность управления запросом на отладку, поэтому в приглашении отладки K>>
  • dbstop error (автоматически отключает режим отладки в строке, которая вызывает ошибку)

Ответ 12

Использование 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

Ответ 13

Мне нравится использовать функциональные дескрипторы по многим причинам. Во-первых, это самая близкая вещь, которую я нашел в 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);

Я просто думаю, что такие вещи классные.

Ответ 14

Вызов кода Java из Matlab

Ответ 15

cellfun и arrayfun для автоматических циклов.

Ответ 16

Оператор двоеточия для манипуляции массивами.

@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

О, и измените массив

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

Ответ 19

Знайте свои свойства оси! Существуют всевозможные вещи, которые вы можете настроить, чтобы настроить свойства построения по умолчанию, чтобы делать то, что вы хотите:

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

(в качестве примера, устанавливает шрифт в 8pt, linestyles всех новых строк, чтобы все были сплошными, а их ширина - 0,3pt, а xtick - [1 3 5 7 9])

Line и figure свойства также полезно, но я больше всего использую свойства оси.

Ответ 20

Быть строгим с указанием размеров при использовании функций агрегации, таких как 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

>> 

То же самое относится к min-функции, которая обычно вычисляет минимумы по столбцам на матрице, пока матрица не состоит только из одной строки. - Затем он вернет минимум по строке, если параметр измерения не указывает иначе, и, возможно, нарушит ваше приложение.

Я почти гарантирую вам, что, следовательно, настройка этих функций агрегации позволит вам в дальнейшем немного отладить работу.

По крайней мере, это было бы для меня.:)

Ответ 21

Чтобы быстро проверить функцию, я использую 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 test script для проверки функции для разных условий ввода.

Ответ 22

Использование 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

Ответ 23

Задание "почему" (полезно для того, чтобы сотрясать меня из теста Matlab runtime-fail debugging trance в 3 часа...)

Ответ 24

Векторизация:

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

Ответ 25

Выполнение модели Simulink непосредственно из script (а не интерактивно) с помощью команды sim. Вы можете делать такие вещи, как принимать параметры из переменной рабочего пространства и многократно запускать sim в цикле, чтобы имитировать что-то, изменяя параметр, чтобы увидеть, как изменяется поведение, и нарисуйте результаты с помощью любых графических команд, которые вам нравятся. Гораздо проще, чем пытаться сделать это в интерактивном режиме, и это дает вам гораздо большую гибкость, чем блоки "осциллографа" Simulink при визуализации результатов. (хотя вы не можете использовать его, чтобы видеть, что происходит в реальном времени во время имитации)

Очень важно знать опции DstWorkspace и SrcWorkspace команды simset. Эти элементы управления, где блоки "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;

Ответ 26

Контурные графики с [c,h]=contour и clabel(c,h,'fontsize',fontsize). Обычно я использую параметр fontsize, чтобы уменьшить размер шрифта, чтобы числа не попадали друг в друга. Это отлично подходит для просмотра значений двухмерных функций без необходимости гасить 3D-графики.

Ответ 27

Использование 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

Ответ 28

Я удивлен, что, хотя люди упоминали подход логического массива индексации массива, никто не упомянул команду find.

например. если x - массив NxMxO

x (x > 20) работает, создавая логический массив NxMxO и используя его для индекса x (что может быть плохо, если у вас большие массивы и вы ищете небольшое подмножество

x (find (x > 20)) работает, генерируя список (т.е. 1x любой) индексов x, удовлетворяющих x > 20, и индексируя 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

Я не могу вспомнить, есть ли более хороший способ.

Ответ 29

-Вы можете сделать ярлык Matlab для файла инициализации с именем startup.m. Здесь я определяю форматирование, точность вывода и параметры графика для моего сеанса Matlab (например, я использую более крупный размер/размер шрифта, так что .fig можно увидеть явно, когда я помещаю их в презентации.) См. Хороший сообщение блога от одного из разработчиков об этом http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/.

-Вы можете загрузить весь цифровой файл ascii с помощью функции "load". Это не особенно быстро, но быстро выполняет задание для прототипирования (не должен ли это быть девизом Matlab?)

- Как упоминалось, оператор двоеточия и векторизация являются спасателями. Винтовые петли.

Ответ 30

х = repmat ([1:10], 3,1); % say, x - пример массива данных

л = х >= 3; % l является логическим вектором (1s/0s), чтобы выделить те элементы в массиве, которые удовлетворяли бы определенному условию.

N = сумма (сумма (l));% N - количество элементов, удовлетворяющих данному условию.

cheers - счастливые скрипты!