Matlab cat() function: index exceeds matrix dimensions - matlab

I am trying to concatenate an array of numbers from 1->(a-1) + (a+1)->n.
I was using the cat function
cat(2, 1:a-1, a+1:n)
but I am getting the error
Index exceeds matrix dimensions.
Unless I am completely mistaken, I am just trying to concatenate two matrices of numbers so I'm not quite sure why I'm getting this error.
I'm trying to accomplish this:
>> a = 3;
>> n = 10;
>> cat(2, 1:a-1, a+1:n)
ans =
[1,2,4,5,6,7,8,9,10]
Is this the wrong way to do it? Any idea why this error is coming up?

Do you have a variable called cat in your workspace?
>> cat(2, 2:3, 4:6) # this works fine
ans =
2 3 4 5 6
>> cat = 1:3; # introduce the variable 'cat'
>> cat(2, 2:3, 4:6) # now it breaks
??? Index exceeds matrix dimensions.

It looks like you have a variable named cat in the workspace. The clean way is, of course, to rename the variable: If you have a sufficiently recent version of Matlab (R2012x, I think), you can replace cat in the first line it gets assigned (select the variable to see the gray ticks to the right of the window, indicating where the variable occurs in the function), and use shift+enter to replace all occurrences. Or you can use the Find/Replace all function (make sure you only replace words, not substrings, though).
If you cannot replace the existing variable name, you can use square brackets for catenation along the first and/or second dimension:
cat(2,a,b)
is equivalent to
[a,b]

Just for completeness, the concatenation you're trying to accomplish can also be achieved like so:
R = 1:n;
R = R(R ~= a)
I personally think this looks cleaner than
R = [1:a-1 a+1:n]
but that's personal; I always feel a little confusion towards something like 1:a-1>5 (is it ((1:a)-1)>5 or (1:(a-1))>5 or (1:a)-(1>5) or ...). I just always have to think for a second, whereas I understand my solution instantly.

Related

Showing command line output without all of the newlines

Let's just say I type 2+3 in MATLAB. It gives me this output :
>> 2+3
ans =
5
Why is the output coming after 2 newlines? How do I correct this ?
Ideally, I would get the following output
ans = 5
You can use the format command to change how the display of variables when printed. In your case, you'll likely want to use the 'compact' option
format compact
This will remove all of the unnecessary newlines.
2+3
% ans=
% 5
Unfortunately, there is no built-in way to display it all on the same line because MATLAB's display is built to deal with multi-dimensional data. You could overload the display command if you really wanted. You can create a folder named #double and then a function named display inside of that
#double/
display.m
Then inside of display.m you could do something like this
function display(x)
% If it's a scalar, then show it all on one line
if isscalar(x)
fprintf('%s = %g\n', inputname(1), x);
else
% Otherwise use the built-in display command
builtin('display', x)
end
end
Then it will automatically be used when you have a double variable
>> 2 + 3
% ans = 5
If you wanted to overload the display of other types of data (uint16, int8, uint8), you would need to do the same as above except put a copy within their # folders as well.

How can I use of norm(a,b) in matlab if a, b are double type?

I must to use angle = atan2(norm(cross(a,b)),dot(a,b)), for calculating the angle between two vectors a,b and these are double type and norm is undefined for this type. How do I resolve this problem? I need to calculate the angle between two vectors this way.
In your comments, you have shown us how you are actually writing out the angle calculation and it is not the same as how you have put it in your post.
atan2(norm(cross(I(i,j,:),I_avg)),dot(I(i,j,:),I_avg));
I is an image you are loading in. I'm assuming it's colour because of the way you are subsetting I. Because I is a 3D matrix, doing I(i,j,:) will give you a 1 x 1 x 3 vector when in fact this has to be a 1D vector. norm does not recognize this structure which is why you're getting this error. Therefore, you need to use squeeze to remove the singleton dimensions so that this will become a 3 x 1 vector, rather than a 1 x 1 x 3 vector. As such, you need to rewrite your code so that you're doing this instead. Bear in mind that in your comments, angle is always overwritten inside the for loop, so you probably want to save the results of each pixel. With this, you probably want to create a 2D array of angles that will store these results. In other words:
I=imread('thesis.jpg');
I = double(I);
angles = zeros(m,n);
I_avg = squeeze(I_avg); %// Just in case
for i=1:m
for j=1:n
pixels = squeeze(I(i,j,:)); %// Add this statement and squeeze
angles(i,j) = atan2(norm(pixels,I_avg)),dot(pixels,I_avg)); %// Change
end
end
Minor note
MATLAB has a built-in function called angle that determines the angle from the origin to a complex number in the complex plane. It is not recommended you call your variable angle as this will unintentionally shadow over the angle function, and any other code that you create from this point onwards may rely on that actual angle function, and you will get unintended results.
Another minor note
Using i and j as loop variables is not recommended. These letters are reserved for the complex number, and this can produce unintentional results. Take a look at this question and post by Shai here - Using i and j as variables in Matlab. As such, it is suggested you use other variable names instead.
As #rayryeng has successfully answered this question, I would like to turn my post into a more general one by sharing my experience in debugging in Matlab. I hope anyone who somehow managed to find this post get more or less thinking about the habits a good programmer should have.
The question goes like: "How would I do if I get errors?"
Here's an excellent article by Eric in which he lists the rule-of-thumbs when you encounter a bug and wish to get rid of it. It's originally been cited by Stackoverflow, and that's the reason I read it.
If you still get no clue / idea how you can play with your code, see how this person does:
Pin-point the buggy line
(The number should start with 0) Make sure before running a script, you clear out any previously stored variables, including the notorious i and j's (you should never see them in any workspace). If any one is needed for the buggy code to run, save('buggy.mat','importantvar') before clear and load('buggy.mat') after clear.
By doing so, you can isolate your buggy code from anything else, which could have bad influences. For example, in a previously called script, there is a line
double = [2,4,6]; % you should never name a variable `double`
and in the next script, you have
>> e = str2num('uint8(200)')
e =
200
>> double(e)
Index exceeds matrix dimensions.
>>
>> f = single(2.36)
f =
2.3600
>> double(f)
Subscript indices must either be real positive integers or
logicals.
>>
The reason is double is no longer an inbuild function, but a user-defined variable. Too bad to pick up a name carelessly!
....anyway, let's clear the workspace and get rid of double.
>> clear
Read the error message, thoroughly.
Now let's begin with OP's problem. The original code (trimmed) goes like this -
img = imread('peppers.png');
a = img(300,200,:);
b = img(200,300,:);
d = norm(cross(a,b));
.... hence the error
Undefined function 'norm' for input arguments of type 'uint8'.
Error in untitled (line 6)
d = norm(cross(a,b));
Most beginners are only interested in the first line of the error message, which by it alone usually doesn't provide any useful help, or only in the red color, which leads to the famous question "my code does not work!"
But think twice. You still have another 2 lines unread! Error in untitled (line 6) says I'm running a script named untitled and the (first) error lies in line 6, and the code in that line is d = norm(cross(a,b));.
Now, at least you know a little more about your code - "My code d = norm(cross(a,b)); doesn't work!"
Although most likely we may also vote this kind of question to get closed, it's still much much better than a simply "It does not work!".
Now we can pin-point the buggy line
try
% this line will raise an error
d = norm(cross(a,b));
catch err
disp(err.message)
end
Look into the functions
First, make sure the inner function cross works as expected -
>> cross(a,b)
ans(:,:,1) =
0
ans(:,:,2) =
255
ans(:,:,3) =
0
>>
Good. So now we can even narrow down the error to the outer norm.
One more thing to mention. You can always find Mathworks' documentation for any in-build function, by typing "matlab function", such as "matlab norm" in Google (or any other search engine) and clicking on the first result. If you prefer, you can also type in Matlab command window doc _function_ such as doc norm and read the doc in Matlab. It's of course a pleasure of us on Stackoverflow to give you the reference by doing the same thing, but it takes a longer time because a human is, in this aspect, always slower than a search engine.
The error reads Undefined function 'norm' for input arguments of type 'uint8'.. So the input for norm should not be uint8, unsigned 8-bit integer. But what should it be?
% why `norm` "does not work"?
% this line runs perfectly well
norm(cross([1,2,3], [4,5,6]))
% so what is working?
class([1,2,3]) % so `norm` works for `double`
One thing we can do now is convert a and b to double precision. Let's try it now.
% try fixing 'uint8' error
a2 = double(a);
b2 = double(b);
whos a b % now they are double, which `norm` should work for
try
% this line will raise an error
d = norm(cross(a2,b2));
catch err
disp(err.message)
end
Now the error becomes Input must be 2-D.. What's wrong with the input?
% what is "must be 2-D" error?
size(a2) % a2 is 3-D
disp(b2) % b2 is also 3-D
This gives output in command window
ans =
1 1 3
(:,:,1) =
255
(:,:,2) =
150
(:,:,3) =
0
In OP's problem, he/she is trying to calculate something about color difference (to the best of my knowledge) which involves the angle between two color vectors in RGB space. So the vectors are needed. With imread, each pixel of the image is stored as 3 elements in the matrix, first 2 dimension being its physical position, the 3 dimension being RGB channel components. Hence pixel(200,300) with color rgb[255,150,0] is stored by us in variable b wihch is a 3-D vector.
By understanding what we need and what Matlab can do, we can combine these two points into one. We need the norm of the cross product of a and b, while the useful information (the 3 component values) is stored in the 3rd dimension. Matlab can calculate the norm of the cross product of a vector with all its information in the 1st dimension. (Here, "dimension" refers to that of the Matlab variable; a vector with 3 elements in its 1st dimension is physically a 3-D vector).
After thinking twice, we are now able to debug our code - just put all 3 elements into the 1st dimension.
% so we want the 3 elements in the 3rd dimension become in the 1st dim
a3 = squeeze(a2);
b3 = reshape(b2,numel(b2),[]);
try
d = norm(cross(a3,b3));
catch err
disp(err.message)
end
d
Bonus: If by default Matlab treats a 3-D vector as a "1-D array", then most probably the cross function has not been working correctly. Let's make a check -
>> clear
>> a = [1,2,3]
a =
1 2 3
>> b=[4,5,6]
b =
4 5 6
>> cross(a,b)
ans =
-3 6 -3
>>
The result should be the same as the one we can get by calculating by hand.
Now if we put the components into the 3rd dimension of the variable -
>> clear
>> a(1,1,:)=[1,2,3]
a(:,:,1) =
1
a(:,:,2) =
2
a(:,:,3) =
3
>> b(1,1,:)=[4,5,6]
b(:,:,1) =
4
b(:,:,2) =
5
b(:,:,3) =
6
>> cross(a,b)
ans(:,:,1) =
-3
ans(:,:,2) =
6
ans(:,:,3) =
-3
>>
.... seems OK. cross also puts the result in the 3rd dimension. In fact, Mathworks' documentation says
If A and B are vectors, then they must have a length of 3.
If A and B are matrices or multidimensional arrays, then they must
have the same size. In this case, the cross function treats A and B as
collections of three-element vectors. The function calculates the
cross product of corresponding vectors along the first array dimension
whose size equals 3.
At last, one thing is always correct to anyone who wants to do something with programming - be cautious and prudent when writing your code.

Select all elements except one in a vector

My question is very similar to this one but I can't manage exactly how to apply that answer to my problem.
I am looping through a vector with a variable k and want to select the whole vector except the single value at index k.
Any idea?
for k = 1:length(vector)
newVector = vector( exluding index k); <---- what mask should I use?
% other operations to do with the newVector
end
Another alternative without setdiff() is
vector(1:end ~= k)
vector([1:k-1 k+1:end]) will do. Depending on the other operations, there may be a better way to handle this, though.
For completeness, if you want to remove one element, you do not need to go the vector = vector([1:k-1 k+1:end]) route, you can use vector(k)=[];
Just for fun, here's an interesting way with setdiff:
vector(setdiff(1:end,k))
What's interesting about this, besides the use of setdiff, you ask? Look at the placement of end. MATLAB's end keyword translates to the last index of vector in this context, even as an argument to a function call rather than directly used with paren (vector's () operator). No need to use numel(vector). Put another way,
>> vector=1:10;
>> k=6;
>> vector(setdiff(1:end,k))
ans =
1 2 3 4 5 7 8 9 10
>> setdiff(1:end,k)
Error using setdiff (line 81)
Not enough input arguments.
That is not completely obvious IMO, but it can come in handy in many situations, so I thought I would point this out.
Very easy:
newVector = vector([1:k-1 k+1:end]);
This works even if k is the first or last element.
%create a logic vector of same size:
l=ones(size(vector))==1;
l(k)=false;
vector(l);
Another way you can do this which allows you to exclude multiple indices at once (or a single index... basically it's robust to allow either) is:
newVector = oldVector(~ismember(1:end,k))
Works just like setdiff really, but builds a logical mask instead of a list of explicit indices.

MATLAB - vector script

I have recently started learning MatLab, and wrote the following script today as part of my practice to see how we can generate a vector:
x = [];
n = 4;
for i = i:n
x = [x,i^2];
end
x
When I run this script I get what I expect, namely the following vector:
x = 0 1 4 9 16
However, if I run the script a second time right afterwards I only get the following output:
x = 16
What is the reason for this? How come I only get the last vector entry as output the second time I run the script, and not the vector in its entirety? If anyone can explain this to me, I would greatly appreciate it.
Beginning with a fresh workspace, i will simply be the complex number 1i (as in x^2=-1). I imagine you got this warning on the first run:
Warning: Colon operands must be real scalars.
So the for statement basically loops over for i = real(1i):4. Note that real(1i)=0.
When you rerun the script again with the variables already initialized (assuming you didn't clear the workspace), i will refer to a variable containing the last value of 4, shadowing the builtin function i with the same name, and the for-loop executes:
x=[];
for i=4:4
x = [x, i^2]
end
which iterates only one time, thus you end up with x=16
you forget to initialize i.
after first execution i is 4 and remains 4.
then you initialize x as an empty vector but because i is 4 the loop runs only once.
clear your workspace and inspect it before and after first execution.
Is it possibly a simple typo?
for i = i:n
and should actually mean
for i = 1:n
as i is (probably) uninitialized in the first run, and therefore 0, it works just fine.
The second time, i is still n (=4), and only runs once.
Also, as a performance-tip: in every iteration of your loop you increase the size of your vector, the more efficient (and more matlaboid) way would be to create the vector with the basevalues first, for example with
x = 1:n
and then square each value by
x = x^2
In Matlab, using vector-operations (or matrix-operations on higher dimensions) should be prefered over iterative loop approaches, as it gives matlab the opportunity to do optimised operations. It is also often more readable that way.

What is your favourite MATLAB/Octave programming trick? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I think everyone would agree that the MATLAB language is not pretty, or particularly consistent. But nevermind! We still have to use it to get things done.
What are your favourite tricks for making things easier? Let's have one per answer so people can vote them up if they agree. Also, try to illustrate your answer with an example.
Using the built-in profiler to see where the hot parts of my code are:
profile on
% some lines of code
profile off
profile viewer
or just using the built in tic and toc to get quick timings:
tic;
% some lines of code
toc;
Directly extracting the elements of a matrix that satisfy a particular condition, using logical arrays:
x = rand(1,50) .* 100;
xpart = x( x > 20 & x < 35);
Now xpart contains only those elements of x which lie in the specified range.
Provide quick access to other function documentation by adding a "SEE ALSO" line to the help comments. First, you must include the name of the function in all caps as the first comment line. Do your usual comment header stuff, then put SEE ALSO with a comma separated list of other related functions.
function y = transmog(x)
%TRANSMOG Transmogrifies a matrix X using reverse orthogonal eigenvectors
%
% Usage:
% y = transmog(x)
%
% SEE ALSO
% UNTRANSMOG, TRANSMOG2
When you type "help transmog" at the command line, you will see all the comments in this comment header, with hyperlinks to the comment headers for the other functions listed.
Turn a matrix into a vector using a single colon.
x = rand(4,4);
x(:)
Vectorizing loops. There are lots of ways to do this, and it is entertaining to look for loops in your code and see how they can be vectorized. The performance is astonishingly faster with vector operations!
Anonymous functions, for a few reasons:
to make a quick function for one-off uses, like 3x^2+2x+7. (see listing below) This is useful for functions like quad and fminbnd that take functions as arguments. It's also convenient in scripts (.m files that don't start with a function header) since unlike true functions you can't include subfunctions.
for closures -- although anonymous functions are a little limiting as there doesn't seem to be a way to have assignment within them to mutate state.
.
% 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's bsxfun, arrayfun, cellfun, and structfun are quite interesting and often save a loop.
M = rand(1000, 1000);
v = rand(1000, 1);
c = bsxfun(#plus, M, v);
This code, for instance, adds column-vector v to each column of matrix M.
Though, in performance critical parts of your application you should benchmark these functions versus the trivial for-loop because often loops are still faster.
LaTeX mode for formulas in graphs: In one of the recent releases (R2006?) you add the additional arguments ,'Interpreter','latex' at the end of a function call and it will use LaTeX rendering. Here's an example:
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');
Not sure when they added it, but it works with R2006b in the text(), title(), xlabel(), ylabel(), zlabel(), and even legend() functions. Just make sure the syntax you are using is not ambiguous (so with legend() you need to specify the strings as a cell array).
Using xlim and ylim to draw vertical and horizontal lines. Examples:
Draw a horizontal line at y=10:
line(xlim, [10 10])
Draw vertical line at x=5:
line([5 5], ylim)
Here's a quick example:
I find the comma separated list syntax quite useful for building function calls:
% Build a list of args, like so:
args = {'a', 1, 'b', 2};
% Then expand this into arguments:
output = func(args{:})
Here's a bunch of nonobvious functions that are useful from time to time:
mfilename (returns the name of the currently running MATLAB script)
dbstack (gives you access to the names & line numbers of the matlab function stack)
keyboard (stops execution and yields control to the debugging prompt; this is why there's a K in the debug prompt K>>
dbstop error (automatically puts you in debug mode stopped at the line that triggers an error)
I like using function handles for lots of reasons. For one, they are the closest thing I've found in MATLAB to pointers, so you can create reference-like behavior for objects. There are a few neat (and simpler) things you can do with them, too. For example, replacing a switch statement:
switch number,
case 1,
outargs = fcn1(inargs);
case 2,
outargs = fcn2(inargs);
...
end
%
%can be turned into
%
fcnArray = {#fcn1, #fcn2, ...};
outargs = fcnArray{number}(inargs);
I just think little things like that are cool.
Using nargin to set default values for optional arguments and using nargout to set optional output arguments. Quick example
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
Invoking Java code from Matlab
cellfun and arrayfun for automated for loops.
Oh, and reverse an array
v = 1:10;
v_reverse = v(length(v):-1:1);
conditional arguments in the left-hand side of an assignment:
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);
Know your axis properties! There are all sorts of things you can set to tweak the default plotting properties to do what you want:
set(gca,'fontsize',8,'linestyleorder','-','linewidth',0.3,'xtick',1:2:9);
(as an example, sets the fontsize to 8pt, linestyles of all new lines to all be solid and their width 0.3pt, and the xtick points to be [1 3 5 7 9])
Line and figure properties are also useful, but I find myself using axis properties the most.
Be strict with specifying dimensions when using aggregation functions like min, max, mean, diff, sum, any, all,...
For instance the line:
reldiff = diff(a) ./ a(1:end-1)
might work well to compute relative differences of elements in a vector, however in case the vector degenerates to just one element the computation fails:
>> 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.
If you specify the correct dimensions to your functions, this line returns an empty 1-by-0 matrix, which is correct:
>> diff(a, [], 2) ./ a(1, 1:end-1)
ans =
Empty matrix: 1-by-0
>>
The same goes for a min-function which usually computes minimums over columns on a matrix, until the matrix only consists of one row. - Then it will return the minimum over the row unless the dimension parameter states otherwise, and probably break your application.
I can almost guarantee you that consequently setting the dimensions of these aggregation functions will save you quite some debugging work later on.
At least that would have been the case for me. :)
The colon operator for the manipulation of arrays.
#ScottieT812, mentions one: flattening an array, but there's all the other variants of selecting bits of an array:
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);
In order to be able to quickly test a function, I use nargin like so:
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;
Later on, I add a unit test script to test the function for different input conditions.
Using ismember() to merge data organized by text identfiers. Useful when you are analyzing differing periods when entries, in my case company symbols, come and go.
%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
Asking 'why' (useful for jarring me out of a Matlab runtime-fail debugging trance at 3am...)
Executing a Simulink model directly from a script (rather than interactively) using the sim command. You can do things like take parameters from a workspace variable, and repeatedly run sim in a loop to simulate something while varying the parameter to see how the behavior changes, and graph the results with whatever graphical commands you like. Much easier than trying to do this interactively, and it gives you much more flexibility than the Simulink "oscilloscope" blocks when visualizing the results. (although you can't use it to see what's going on in realtime while the simulation is running)
A really important thing to know is the DstWorkspace and SrcWorkspace options of the simset command. These control where the "To Workspace" and "From Workspace" blocks get and put their results. Dstworkspace defaults to the current workspace (e.g. if you call sim from inside a function the "To Workspace" blocks will show up as variables accessible from within that same function) but SrcWorkspace defaults to the base workspace and if you want to encapsulate your call to sim you'll want to set SrcWorkspace to current so there is a clean interface to providing/retrieving simulation input parameters and outputs. For example:
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;
Contour plots with [c,h]=contour and clabel(c,h,'fontsize',fontsize). I usually use the fontsize parameter to reduce the font size so the numbers don't run into each other. This is great for viewing the value of 2-D functions without having to muck around with 3D graphs.
Vectorization:
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);
Using persistent (static) variables when running an online algorithm. It may speed up the code in areas like Bayesian machine learning where the model is trained iteratively for the new samples. For example, for computing the independent loglikelihoods, I compute the loglikelihood initially from scratch and update it by summing this previously computed loglikelihood and the additional loglikelihood.
Instead of giving a more specialized machine learning problem, let me give a general online averaging code which I took 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
Then, the calls will give the following results
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
I'm surprised that while people mentioned the logical array approach of indexing an array, nobody mentioned the find command.
e.g. if x is an NxMxO array
x(x>20) works by generating an NxMxO logical array and using it to index x (which can be bad if you have large arrays and are looking for a small subset
x(find(x>20)) works by generating list (i.e. 1xwhatever) of indices of x that satisfy x>20, and indexing x by it. "find" should be used more than it is, in my experience.
More what I would call 'tricks'
you can grow/append to arrays and cell arrays if you don't know the size you'll need, by using end + 1 (works with higher dimensions too, so long as the dimensions of the slice match -- so you'll have to initialize x to something other than [] in that case). Not good for numerics but for small dynamic lists of things (or cell arrays), e.g. parsing files.
e.g.
>> x=[1,2,3]
x = 1 2 3
>> x(end+1)=4
x = 1 2 3 4
Another think many people don't know is that for works on any dim 1 array, so to continue the example
>> for n = x;disp(n);end
1
2
3
4
Which means if all you need is the members of x you don't need to index them.
This also works with cell arrays but it's a bit annoying because as it walks them the element is still wrapped in a cell:
>> for el = {1,2,3,4};disp(el);end
[1]
[2]
[3]
[4]
So to get at the elements you have to subscript them
>> for el = {1,2,3,4};disp(el{1});end
1
2
3
4
I can't remember if there is a nicer way around that.
-You can make a Matlab shortcut to an initialization file called startup.m. Here, I define formatting, precision of the output, and plot parameters for my Matlab session (for example, I use a larger plot axis/font size so that .fig's can be seen plainly when I put them in presentations.) See a good blog post from one of the developers about it http://blogs.mathworks.com/loren/2009/03/03/whats-in-your-startupm/ .
-You can load an entire numerical ascii file using the "load" function. This isn't particularly fast, but gets the job done quickly for prototyping (shouldn't that be the Matlab motto?)
-As mentioned, the colon operator and vectorization are lifesavers. Screw loops.
x=repmat([1:10],3,1); % say, x is an example array of data
l=x>=3; % l is a logical vector (1s/0s) to highlight those elements in the array that would meet a certain condition.
N=sum(sum(l));% N is the number of elements that meet that given condition.
cheers -- happy scripting!