I don't understand why I can't find any clear answer on this! Such a basic thing...
I have a normal 2D matrix, such as this one:
matrix = zeros(w, h);
Where w, h ∈ Z+, which means w and h are positive integers greater than zero.
I need to loop through the matrix and do something with it's element. For this task, we can assume h=3. Therefore, I tried this:
test = zeros(w, 3);
for i = 1:test
point = test(:,i);
[point(0), point(1), point(2)] = MY_CONVERSION(point(0), point(1),point(2));
test(:,i) = point;
end
The MY_CONVERSION is varargin function and for 3 parameters defined as:
function [rho, alpha, z] = MY_CONVERSION(r, alpha, epsilon)
Of course, in real code the test contains data, not just zeros. But this code alone could, for example, fill matrix with random numbers. But it doesn't work.
I also tried using three variables to store the column values:
for i = 1:Xi
[a,b,c] = Xi(:,i);
[a,b,c] = mysph2cyl(a, b, c);
rho(:,i) = a,b,c;
end
Matlab marks it as incorrect syntax:
An assignment statement makes an assignment to multiple values, but
the expression on the right side of the assignment does not appear to
produce multiple values.
The first piece of code is what you need to get it working. However, your for loop is incorrect. You probably want to iterative over all of the columns, so do for i = 1 : size(test,2), not test. size(test,2) determines how many columns your matrix has.
Therefore:
test = zeros(w, 3);
for i = 1:size(test,2) %// Change here
point = test(:,i);
[point(0), point(1), point(2)] = MY_CONVERSION(point(0), point(1),point(2));
test(:,i) = point;
end
Also, your second piece of code, you need to fix that for loop problem like I mentioned above. The first statement inside the for loop is superfluous. You don't need it. The third line of code needs to have [] surrounding a,b,c.
First, matrix = zeros(w, h); creates confusion: you are probably thinking of w as width and h as height. But the first argument of zeros is height: for example, zeros(2,3) is
0 0 0
0 0 0
Generally: row index first, column index second.
Then you have for i = 1:test but test is a matrix. You need a number here.
Here is a working example similar to your first fragment:
w = 2; h =3;
test = zeros(w, h);
for i = 1:h
point = test(:,i);
point = cos(point)*i; % sample conversion
test(:,i) = point;
end
Output:
1 2 3
1 2 3
Related
I have a vector that has 1's in some places, and I want to create a diagonal using the vector. The vector is called one_vec_two:
n = 4;
one_vec_two = zeros(n*n, 1);
one_vec_two(1,1) = 1;
for k=0:(n-1)
one_vec_two(k*n+1, 1) = 1;
end
non_zero_vecs = [one_vec_two];
placement = [n-1];
A = spdiags(non_zero_vecs, placement, n*n, n*n);
fullA = full(A);
disp(A)
The first element of the vector one_vec_two is a 1:
>> one_vec_two(1)
ans =
1
And, I placed the vector starting at diagonal n-1, which is 3. But, when I go to column 4, I don't see it:
>> fullA(1,4)
ans =
0
Why isn't MATLAB putting my vector in the correct spot?
As per the doc for spdiag,
Note In this syntax, if a column of B is longer than the diagonal it is replacing, and m >= n, spdiags takes elements of super-diagonals from the lower part of the column of B, and elements of sub-diagonals from the upper part of the column of B.
it is placing the lower part of your vector into the location specified. Hence the result is as expected.
It looks like you want something like
A = spdiags(non_zero_vecs([end-placement+1:end 1:end-placement]), placement, n*n, n*n)
or
A = spdiags(non_zero_vecs, -placement, n*n, n*n)'
which both do the same thing, just in slightly different ways.
I need some help to vectorize the following operation since I'm a little confused.
So, I have a m-by-2 matrix A and n-by-1 vector b. I want to create a n-by-1 vector c whose entries should be the values of the second column of A whose line is given by the line where the correspondent value of b would fall...
Not sure if I was clear enough. Anyway, the code below does compute c correctly so you can understand what is my desired output. However, I want to vectorize this function since my real n and m are in the order of many thousands.
Note that values of bare non-integer and not necessarily equal to any of those in the first column of A (these ones could be non-integers too!).
m = 5; n = 10;
A = [(0:m-1)*1.1;rand(1,m)]'
b = (m-1)*rand(n,1)
[bincounts, ind] = histc(b,A(:,1))
for i = 1:n
c(i) = A(ind(i),2);
end
All you need is:
c = A(ind,2);
I have an array with n dimensions, and I have a sequence along one dimension at a certain location on all other dimensions. How do I find the location of this sequence? Preferably without loops.
I use matlab. I know what dimension it should be in, but the sequence isnt necessarily there. Find and == dont work. I could make an nd find function using crosscorrelation but Im guessing this is already implemented and I just dont know what function to call.
example:
ND = rand(10,10,10,10);
V = ND(randi(10),randi(10),randi(10),:);
[I1, I2, I3] = find(ND==V);
Edit: The sequence to be found spans the entire dimension it is on, I did not mention this in my original formulation of the problem. Knedlsepp`s solution solves exactly the problem I had, but Luis' solution solves a more general problem for when the sequence doesn't necessarily span the entire dimension.
As there are multiple ways to interpret your question, I will clarify: This approach assumes a 1D sequence of size: numel(V) == size(ND, dimToSearch). So, for V = [1,2] and ND = [1,2,1,2] it is not applicable. If you want this functionality go with Luis Mendo's answer, if not this will likely be faster.
This will be a perfect opportunity to use bsxfun:
We start with some example data:
ND = rand(10,10,10,10);
V = ND(3,2,:,3);
If you don't have the vector V given in the correct dimension (in this case [1,1,10,1]) you can reshape it in the following way:
dimToSearch = 3;
Vdims = ones(1, ndims(ND));
Vdims(dimToSearch) = numel(V);
V = reshape(V, Vdims);
Now we generate a cell that will hold the indices of the matches:
I = cell(1, ndims(ND));
At this point we compute the size of ND if it were collapsed along the dimension dimToSearch (we compute dimToSearch according to V, as at this point it will have the correct dimensions):
dimToSearch = find(size(V)>1);
collapsedDims = size(ND);
collapsedDims(dimToSearch) = 1;
Finally the part where we actually look for the pattern:
[I{:}] = ind2sub(collapsedDims, find(all(bsxfun(#eq, ND, V), dimToSearch)));
This is done in the following way: bsxfun(#eq, ND, V) will implicitly repmat the array V so it has the same dimensions as ND and do an equality comparison. After this we do a check with all to see if all the entries in the dimension dimToSearch are equal. The calls to find and ind2sub will then generate the correct indices to your data.
Let d be the dimension along which to search. I'm assuming that the sought sequence V may be shorter than size(ND,d). So the sequence may appear once, more than once, or never along each dimension-d- "thread".
The following code uses num2cell to reshape ND into a cell array such that each dimension-d-thread is in a different cell. Then strfind is applied to each cell to determine matches with V, and the result is a cell array with the same dimensions as ND, but where the dimension d is a singleton. The contents of each cell tell the d-dimension-positions of the matches, if any.
Credit goes to #knedlsepp for his suggestion to use num2cell, which greatly simplified the code.
ND = cat(3, [1 2 1 2; 3 4 5 6],[2 1 0 5; 0 0 1 2] ); %// example. 2x4x2
V = 1:2; %// sought pattern. It doesn't matter if it's a row, or a column, or...
d = 2; %// dimension along which to search for pattern V
result = cellfun(#(x) strfind(x(:).', V(:).'), num2cell(ND,d), 'UniformOutput', 0);
This gives
ND(:,:,1) =
1 2 1 2
3 4 5 6
ND(:,:,2) =
2 1 0 5
0 0 1 2
V =
1 2
result{1,1,1} =
1 3 %// V appears twice (at cols 1 and 3) in 1st row, 1st slice
result{2,1,1} =
[] %// V doesn't appear in 2nd row, 1st slice
result{1,1,2} =
[] %// V appears appear in 1st row, 2nd slice
result{2,1,2} =
3 %// V appears once (at col 3) in 2nd row, 2nd slice
One not very optimal way of doing it:
dims = size(ND);
Vrep = repmat(V, [dims(1), dims(2), dims(3), 1]);
ND_V_dist = sqrt(sum(abs(ND.^2-Vrep.^2), 4));
iI = find(ND_V_dist==0);
[I1, I2, I3] = ind2sub([dims(1), dims(2), dims(3)], iI);
I've been searching the net for a couple of mornings and found nothing, hope you can help.
I have an anonymous function like this
f = #(x,y) [sin(2*pi*x).*cos(2*pi*y), cos(2*pi*x).*sin(2*pi*y)];
that needs to be evaluated on an array of points, something like
x = 0:0.1:1;
y = 0:0.1:1;
w = f(x',y');
Now, in the above example everything works fine, the result w is a 11x2 matrix with in each row the correct value f(x(i), y(i)).
The problem comes when I change my function to have constant values:
f = #(x,y) [0, 1];
Now, even with array inputs like before, I only get out a 1x2 array like w = [0,1];
while of course I want to have the same structure as before, i.e. a 11x2 matrix.
I have no idea why Matlab is doing this...
EDIT 1
Sorry, I thought it was pretty clear from what I wrote in the original question, but I see some of you asking, so here is a clarification: what I want is to have again a 11x2 matrix, since I am feeding the function with arrays with 11 elements.
This means I expect to have an output exactly like in the first example, just with changed values in it: a matrix with 11 rows and 2 columns, with only values 0 in the first column and only values 1 in the second, since for all x(i) and y(i) the answer should be the vector [0,1].
It means I expect to have:
w = [0 1
0 1
0 1
...
0 1]
seems pretty natural to me...
You are defining a function f = #(x,y) [0, 1]; which has the input parameters x,y and the output [0,1]. What else do you expect to happen?
Update:
This should match your description:
g=#(x,y)[zeros(size(x)),ones(size(y))]
g(x',y')
Defining an anonymous function f as
f = #(x,y) [0,1];
naturally returns [0,1] for any inputs x and y regardless of the length of those vectors.
This behavior puzzled me also until I realized that I expected f(a,b) to loop over a and b as if I had written
for inc = 1:length(a)
f(a(inc), b(inc))
end
However, f(a,b) does not loop over the length of its inputs, so it merely returns [0,1] regardless of the length of a and b.
The desired behavior can be obtained by defining f as
g=#(x,y)[zeros(size(x)),ones(size(y))]
as Daniel stated in his answer.
I have a solution to creating a vector for just one element of a matrix:
[dx,dy] = gradient(Im);
orient11 = [(-dx(1,1)) (dy(1,1)) 0];
where
size(orient11) =
0 0 0
ie for the first element of orient, namely orient11, is a vector. How do I do this for all the other elements, so I have orient12, orient13....orientnn. I know I need a for loop, however what object do I store the vectors into from the for loop? I have discovered I can't create a matrix of vectors.
Thanks in advance.
You can try building an N-by-N-by-3 matrix, but it won't be so convenient to manipulate. This is because extracting a vector from this matrix would yield a 1-by-1-by-3 vector, which you would need to reshape. Definitely not fun.
Instead, I suggest that you build an N-by-N cell array of 1-by-3 vectors, like so:
[dx, dy] = gradient(Im);
vec = #(i)[-dx(i), dy(i), 0];
orient = arrayfun(vec, reshape(1:numel(dx), size(dx)), 'UniformOutput', 0);
To access a vector, use the curly braces. For example, the vector at the (1, 2) position would be:
orient12 = orient{1, 2};
Hope it helps!
v = -2:0.2:2;
[x,y] = meshgrid(v);
z = x .* exp(-x.^2 - y.^2);
[px,py] = gradient(z,.2,.2);
orient11 = [(-px(1,1)) (py(1,1)) 0]; % based off of your concatination there.
size(orient11)
I then get:
ans =
1 3
If you're looking to just grab the first column of data from the gradients you have and want to just stack zeros with them, you can do this:
orient11 = [(-px(:,1)) (py(:,1)) zeros(size(px,1),1)];
Instead of a for loop.
Update:
Orient = zeros(size(px,1),3,size(px,2));
for n = 1:size(px,1)
Orient(:,:,n) = [(-px(:,n)) (py(:,n)) zeros(size(px,1),1)];
end
The layout of Orient is now your -px, py, 0 in layers. Each layer represents the column from the initial data. So if you wanted to get access to row 4 column 14, you would call Orient(4,:,14).
Hope that makes sense and helps!