I have a matrix of two columns and six rows, and want to build a second one with the following code:
for i=2
if F(:,i)<50
G(:,i) = 1
end
end
But nothing happens...
The idea was that if a value in the second column in F was less than 50, then the corresponding value in G would be 1.
Sorry for probably basic question, but no idea why this doesn't work. If I change to evaluate whether the F value ~= 50, then everything works as it should.
Thanks for any help.
Your if statement is only executed once - not once per element. While F(:,i)<50 returns an array of values, the if is either true or false; consequently, the next line is only executed once (either on all elements in G(:,i), or none of them).
For example, see this piece of code:
if(1 < [0 1 2]), disp('true'); end
It will produce no output, even though it is true for the third element. On the other hand,
if(1 < [2 3 4]), disp('true'); end
does produce output...
In general, the following:
1 < [0 1 2]
produces
0 0 1
Not sure why you say it doesn't work for < but it does work for ~=. Maybe there are no elements equal to 50, so it only "seems" to work?
In general, there is a better way to do what you want, with a single line:
G(F(:,2)<50,2)=1
This uses "logical indexing", and is much faster than looping. It will consider each element of F(:,2), and modify the corresponding element in G.
One final comment: it is not great practice to use the variable i since it has a built in value of sqrt(-1). If you have code anywhere that relies on it having that value, then accidentally overwriting it with any other value would break that. It's not the problem with your code today - but why set yourself up for a problem in the future.
Related
In Matlab, I have a 2x3 matrix, A, like this one:
A = [1 2 3; 4 5 6];
This matrix is defined inside of a function which takes a parameter, T. There are two cases that I need to take care of:
T < 10
T >= 10
If the user entered, say, T=40, then the 2nd row of A should be selected to make the calculations. On the other hand, if say T=5, the first row of A should be selected.
I can write a simple if-else condition like this:
if (T<10)
b = A(1,:) * ... %Do whatever with the first row
else
b = A(2,:) * ... %Do whatever with the second row
end
However I was wondering if it's possible to play around with Matlab indexes to save myself the overhead of having to write this if-else condition all around my code (this condition has to be checked many times, in different parts of my program).
For example, I was hoping to reach a simple expression like A(T<10, :) which would work fine if T<10 but for T>=10 would return an empty matrix.
I've been racking my brains for some hours but I'm a bit of a novice in optimising Matlab scripts. Could anyone kick me in the right direction?
You can use the following method:
A((T>=10) + 1, :)
I struggle with printing text in my Matlab GUI.
I have code like this in my callback:
if Lia == ismember(handles.T(1:3),(1,1,1))
set(handles.t1, 'String', 'good day');
end
The problem is, I don't know how to check if in my array indexes from 1 to 3 I got this numbers: 1,1,1. I was looking to the documentation but it appears it says nothing about that (or I simply cannot find the proper answer).
You can simply use all and check to see if every element in the first three slots of your array match the values of 1 explicitly. I don't know the shape of your array so I'm going to force it to be a column vector. If the first three slots of the array was a row or column vector and if we assumed that the values of 1 are a column or row vector respectively then you're going to get a rather unpleasant surprise:
h = handles.T(1:3);
if all(h(:) == [1; 1; 1])
set(handles.t1, 'String', 'good day');
end
Note that I could have simply done all(h(:) == 1) as a special case since we are performing a comparison of every element in an array with a single value. However, I have a feeling that this may change for you, so I've decided to explicitly make a vector of 1s so you can change the contents of what you want to compare to at a later time.
In Matlab, suppose I would like to create a 0-vector of length L, except with a 1 at index i?
For example, something like:
>> mostlyzeros(6, 3)
ans =
0 0 1 0 0 0
The purpose is so I can use it as a 'selection' vector which I'll multiply element-wise with another vector.
The simplest way I can think of is this:
a = (1:N)==m;
where N>=m. Having said that, if you want to use the resulting vector as a "selection vector", I don't know why you'd multiply two vectors elementwise, as I would expect that to be relatively slow and inefficient. If you want to get a vector containing only the m-th value of vector v in the m-th position, this would be a more straightforward method:
b = ((1:N)==m)*v(m);
Although the most natural method would have to be this:
b(N)=0;
b(m)=v(m);
assuming that b isn't defined before this (if b is defined, you need to use zeros rather than just assigning the Nth value as zero - it has been my experience that creating a zero vector or matrix that didn't exist before that is most easily done by assigning the last element of it to be zero - it's also useful for extending a matrix or vector).
I'm having a hard time thinking of anything more sensible than:
Vec = zeros(1, L);
Vec(i) = 1;
But I'd be happy to be proven wrong!
UPDATE: The one-liner solution provided by #GlenO is very neat! However, be aware that if efficiency is the chief criteria, then a few speed tests on my machine indicate that the simple method proposed in this answer and the other two answers is 3 or 4 times faster...
NEXT UPDATE: Ah! So that's what you mean by "selection vectors". #GlenO has given a good explanation of why for this operation a vector of ones and zeros is not idiomatic Matlab - however you choose to build it.
ps Try to avoid using i as a subscript, since it is actually a matlab function.
Just for the fun of it, another one-liner:
function [out] = mostlyzeros(idx, L)
out([L, idx]) = [0 1];
I can think of:
function mostlyones(m,n)
mat=zeros(1,m);
mat(n)=1;
Also, one thing to note. In MATLAB, index starts from one and not from zero. So your function call should have been mostlyzeros(6,3)
I would simply create a zero-vector and change whatever value you like to one:
function zeroWithOne(int numOfZeros, int pos)
a = zeros(numOfZeros,1);
a(pos) = 1;
Another one line option, which should be fast is:
vec = sparse(1, ii, 1, 1, L);
Could somebody explain the following code snippet? I have no background in computer science or programming and just recently became aware of Matlab. I understand the preallocation part from data=ceil(rand(7,5)*10)... to ...N*(N-1)/2).
I need to understand every aspect of how matlab processes the code from kk=0 to the end. Also, the reasons why the code is codified in that manner. There's no need to explain the function of: bsxfun(#minus), just how it operates in the scheme of the code.
data=ceil(rand(7,5)*10);
N = size(data,2);
b=cell(N-1,1);
c=NaN(size(data,1),N*(N-1)/2);
kk=0;
for ii=1:N-1
b{ii} = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
c(:,kk+(1:N-ii)) = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
kk=kk+N-ii;
end
Start at zero
kk=0;
Loop with ii going from 1 up to N-1 incrementing by 1 every iteration. Type 1:10 in the command line of matlab and you'll see that it outputs 1 2 3 4 5 6 7 8 9 10. Thuis colon operator is a very important operator to understand in matlab.
for ii=1:N-1
b{ii} = ... this just stores a matrix in the next element of the cell vector b. Cell arrays can hold anything in each of their elements, this is necessary as in this case each iteration is creating a matrix with one fewer column than the previous iteration.
data(:,ii) --> just get the iith column of the matrix data (: means get all the rows)
data(:, ii + 1:end) means get a subset of the matrix data consisting of all the rows but only of columns that appear after column ii
bsxfun(#minus, data(:,ii), data(:,ii+1:end)) --> for each column in the matrix data(:, ii+1:end), subtract the single column data(:,ii)
b{ii} = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
%This does the same thing as the line above but instead of storing the resulting matrix of the loop in a separate cell of a cell array, this is appending the original array with the new matrix. Note that the new matrix will have the same number of rows each time but one fewer column, so this appends as new columns.
%c(:,kk + (1:N-ii)) = .... --> So 1:(N-ii) produces the numbers 1 up to the number of columns in the result of this iteration. In matlab, you can index an array using another array. So for example try this in the command line of matlab: a = [0 0 0 0 0]; a([1 3 5]) = 1. The result you should see is a = 1 0 1 0 1. but you can also extend a matrix like this so for example now type a(6) = 2. The result: a = 1 0 1 0 1 2. So by using c(:, 1:N-ii) we are indexing all the rows of c and also the right number of columns (in order). Adding the kk is just offsetting it so that we do not overwrite our previous results.
c(:,kk+(1:N-ii)) = bsxfun(#minus,data(:,ii),data(:,ii+1:end));
Now we just increment kk by the number of new columns we added so that in the next iteration, c is appended at the end.
kk=kk+N-ii;
end;
I suggest that you put a breakpoint in this code and step through it line by line and look at how the variables change in matlab. To do this click on the little dashed line next to k=0; in the mfile, you will see a red dot appear there, and then run the code. The code will only execute as far as the dot, you are now in debug mode. If you hover over a variable in debug mode matlab will show its contents in a tool tip. For a really big variable check it out in the workspace. Now step through the code line by line and use my explanations above to make sure you understand how each line is changing each variable. For more complex lines like b{ii} = bsxfun(#minus,data(:,ii),data(:,ii+1:end)); you should highlight code snippets and ruin these in the command line to see what each part is doing so for example run data(:,ii) to see what that does and then try data(:,ii+1:end)) or even just ii+1:end (well in that case it wont work, replace end with size(data, 2)). Debugging is the best way to understand code that confuses you.
bsxfun(#minus,A,B)
is almost the same as
A-B
The difference is that the bsxfun version will handle inputs of different size: In each dimension (“direction,” if you find it easier to think about that way), if one of the inputs is scalar and the other one a vector, the scalar one will simply be repeated sufficiently often.
http://www.mathworks.com/help/techdoc/ref/bsxfun.html
I'm trying to program a Matlab to list all permutations of the numbers 1 through n in lexicographic order. What I have so far is below. I am using recursion to try and write a program that will work for n=3 first, and then see if I can gain insight into writing the program for any n. So far I have 2 of the 6 columns for n=3: P=[1 2 3;1 3 2]. I need the next two columns to simply swap the ones and the twos. I don't know how to begin to do that.
function [P] = shoes(n)
if n == 1
P = 1;
elseif n == 2
P = [1 2; 2 1];
else
T = shoes(n-1) + 1;
G = ones(factorial(n-1),1);
P(1:2,1:3) = [G T];
end
See the documentation for a start. If by lexicographical order you mean alphabetical by english name, you may want to populate your input with the names, sort them, then permute that.
If I've misunderstood what you're wanting, comment or edit the question & I'll check back later.
Hints:
The permutations of an empty list are easy to find.
Induction is an important concept in mathematics. You should be familiar with it.
The environment you are working in supports recursion
The permutations of a longer list can be produced in the order you want by recursion; first figure out what you want the first element to be, and then figure out the rest.
If you get stuck again, edit the question posting what you've gotten so far and where/why you think you're stuck.
Hints after seeing your code.
Your core function permutes a vector, and so should take a vector as argument, not an integer
Don't start solving the n=3 case; try the n=0 case (it's []) and then go straight to the n=20 case.
Think about the n=20 case before you write any code. What is the first column going to look like? Are there any examples of the n=19 case hidden in the answer to the n=20 case? (The answer is yes, and they are all different).
Reread the first set of hints
You appear to have asked this question twice. Instead of reposting questions, you should simply click the "edit" link below your question and update it. I'll repost here the answer I gave to your other question, but you should really remove one of them.
If you have the following matrix:
A = [1 2 3; 1 3 2];
and you want all the ones to become twos and the twos to become ones, the following would be the simplest way to do it:
B = A;
B(A == 1) = 2;
B(A == 2) = 1;