I got a large vector vec of size n x 1 (with n a huge number). All values in vec are 0 or 1. The vector consists out of blocks of size m and in each block, only one of these two values shall be included.
So as to ensure this condition, I loop over each start element within an block and copy this value into all the entries of the respective block:
for i = 1:m:n
if vec(i) == 1
vec(i:i+m-1) = 1;
else
vec(i:i+m-1) = 0;
end
end
How can I achieve this without loosing a loop so as to better use MATLABs vectorization parallelization? Thanks in advance
You can use repelem:
vec = repelem(vec(1:m:n), m);
Related
I have a matrix 1000x1000x50 and I performed a function on each vector along the third dimension in a loop (1,000,000 vectors, 50 elements long). When I try to view any specific element where m=n, i.e. (1000,1000,40) , a nonzero value is displayed. However, when I try to view an element where m =/= n, i.e. (1000,1001,40), only a 0 is returned. I know that (1001,1001,40) has a nonzero value, and I know that the original matrix had a nonzero element at (1000,1001,40).
Here's the loop I used:
mymatrix_new = zeros(size(mymatrix));
for i=1:length(mymatrix)
mymatrix_new(i,i,:) = wdenoise(squeeze(mymatrix(i,i,:)));
end
For the values that DO display, the result is what I expected- a smoothed signal. I just don't understand why certain elements that are nonzero are displaying as zero when the m and n indices are't identical.
You are iterating and updating only the cells that have m == n. This happens because you use a single for loop. All other values are not visited and are never updated, this is why they remain zero.
If you look at your foor loop:
for i=1:length(mymatrix)
In the first iteration i = 1 and it will update:
mymatrix_new(1,1,:) = wdenoise(squeeze(mymatrix(1,1,:)));
In the second iteration i = 2 and it will update:
mymatrix_new(2,2,:) = wdenoise(squeeze(mymatrix(2,2,:)));
As you can see, you never update mymatrix_new(1, 2) or any cell other than the ones that have m == n == i
You need to use two nested for loops, such that you update all combinations of i and j
mymatrix_new = zeros(size(mymatrix));
for i=1:length(mymatrix)
for j=1:length(mymatrix) % Here it assumes the matrix is a square
mymatrix_new(i,j,:) = wdenoise(squeeze(mymatrix(i,j,:)));
end
end
I have a 64 X 64 matrix that I need to find the column-wise mean values for.
However, instead of dividing by the total number of elements in each column (i.e. 64), I need to divide by the total number of non-zeros in the matrix.
I managed to get it to work for a single column as shown below. For reference, the function that generates my matrix is titled fmu2(i,j).
q = 0;
for i = 1:64
if fmu2(i,1) ~= 0;
q = q + 1;
end
end
for i = 1:64
mv = (1/q).*sum(fmu2(i,1));
end
This works for generating the "mean" value of the first column. However, I'm having trouble looping this procedure so that I will get the mean for each column. I tried doing a nested for loop, but it just calculated the mean for the entire 64 X 64 matrix instead of one column at a time. Here's what I tried:
q = 0;
for i = 1:64
for j = 1:64
if fmu2(i,j) ~= 0;
q = q +1;
end
end
end
for i = 1:64
for j = 1:64
mv = (1/q).*sum(fmu2(i,j));
end
end
Like I said, this just gave me one value for the entire matrix instead of 64 individual "means" for each column. Any help would be appreciated.
For one thing, do not call the function that generates your matrix in each iteration of a loop. This is extremely inefficient and will cause major problems if your function is complex enough to have side effects. Store the return value in a variable once, and refer to that variable from then on.
Secondly, you do not need any loops here at all. The total number of nonzeros is given by the nnz function (short for number of non-zeros). The sum function accepts an optional dimension argument, so you can just tell it to sum along the columns instead of along the rows or the whole matrix.
m = fmu2(i,1)
averages = sum(m, 1) / nnz(m)
averages will be a 64-element array with an average for each column, since sum(m, 1) is a 64 element sum along each column and nnz(m) is a scalar.
One of the great things about MATLAB is that it provides vectorized implementations of just about everything. If you do it right, you should almost never have to use an explicit loop to do any mathematical operations at all.
If you want the column-wise mean of non-zero elements you can do the following
m = randi([0,5], 5, 5); % some data
avg = sum(m,1) ./ sum(m~=0,1);
This is a column-wise sum of values, divided by the column-wise number of elements not equal to 0. The result is a row vector where each element is the average of the corresponding column in m.
Note this is very flexible, you could use any condition in place of ~=0.
Hello I'm new to Matlab.
I've written this script :
k2=2*pi();
z1 = 1;
z2 = 2;
z3 = 4;
for l = linspace(0,1,11)
A = [ -1 1 1 0 ; 1 z1/z2 -z1/z2 0 ; 0 exp(-i*k2*l) exp(i*k2*l) -1 ; 0 exp(- i*k2*l) -exp(i*k2*l) -z2/z3];
B = [ 1 ; 1 ; 0 ; 0];
D = inv(A);
C = mtimes(D,B) ;
display(C)
r = C(1,1); % this is supposed to set r = the 1,1 element in the matrix C
t = C(1,4); % see above
end
My idea for taking the values of r and t from C didnt appear to work. How can I do this properly?
Also I want to plot a graph of |r|,|t|, arg(r) and arg(t) for each value of l, my for loop overwrites the values of r and t? how can I either plot one point per loop or make r and t assign the new values so that they become lists of data.
Thanks a lot!
Matlab sets the first dimension of a matrix as row number (i.e. y position).
So you want t=C(4, 1), as you should see that the size of C is 4x1. As a note Matlab is quite good at suppressing singleton dimensions so you could do also do C(1) and C(4).
For your second point you want to set a particular element of r and t in each loop. This is the same as when you access at particular element of C when setting the values. For your case you can use the index l to determine the element. Remembering that in matlab arrays start at element 1 (not 0 as in many other languages). So you want something like r(l+1)=C(1); (or change l to start at 1).
In the more general case if you are not looping over an integer for some reason you may need to create a separate counter variable which you increase in the loop. Also it is good practice to preallocate such arrays when the size is known beforehand, often by r=zeros(11, 1) or similar (note: zeros(11) is an 11x11 matrix). This isn't significant in this case but can drastically increase execution time for large multi-dimensional arrays so is a good practice.
I have a 512X512 size of image and I have made 4x4 overlapping blocks for the entire image.How can i count the number of overlapping blocks and save it in an Array in matlab.
I have done like below for 4x4 overlapping blocks. Now how to count the no of blocks and store it using an Array.
[e f] = size(outImg);
l=0;
for i=2:e-2
for j=2:f-2
H =double(outImg((i-1:i+2),(j-1:j+2)));
eval(['out_' num2str(l) '=H']);
l=l+1
end;
end;
From what I understand the question, you want to know how many blocks of 4x4 can fit in the image, and then store them.
Calculating the number of blocks is trivial, in the code that you give as example, l is the number of element counted. Of course, that its value is deterministic (determined by f and e). No need to loop over them to get the value of the count.
count = (f-3)*(e-3);
If you want to save the values in an array (assuming that you mean here a matrix and not a cell array) you need to decide how to represent it, you can store it as a 4D e-3 x f-3 x 4 x 4 matrix (as #Steffen suggested), or as a 3D 4 x 4 x count matrix, I think that the later is more intuitive. In any case you should assign the memory for the matrix in advance and not on the fly:
[e f] = size(outImg);
count = (f-3)*(e-3);
outMat = zeros(4,4,count); % assign the memory for the matrix
l = 0;
for i=2:e-2
for j=2:f-2
l = l + 1;
outMat(:,:,l) = double(outImg((i-1:i+2),(j-1:j+2)));
end;
end;
The number of blocks is stored as both count and l, but calculating count in advance allows to assign the needed memory in advance, the i block is stored as outMat(:,:,i).
An implementation using the 4D matrix would be:
[e f] = size(outImg);
count = (f-3)*(e-3);
outMat = zeros((f-3),(e-3),4,4); % assign the memory for the matrix
for i=2:e-2
for j=2:f-2
outMat(i,j,:,:) = double(outImg((i-1:i+2),(j-1:j+2)));
end;
end;
In this case, l isn't needed and each block (indexed i,j) is located at outMat(i,j,:,:)
Regarding cell array vs. a matrix, since a matrix requires a continuous place in the memory, you may want to consider using a cell array instead of a matrix. A 512x512x4 matrix of doubles requires (assuming 8 Byte representation) 8MB (512*512*8*4 = 8*1024*1024). If the dimensions were bigger, or if you are strapped for (continuous) memory a cell array may be a better solution. You can read more about the difference at Difference between cell and matrix in matlab?.
The implementation would be very similar.
[e f] = size(outImg);
count = (f-3)*(e-3);
outArray = cell(1,count);
l = 0;
for i=2:e-2
for j=2:f-2
l = l + 1;
outArray{1,l} = double(outImg((i-1:i+2),(j-1:j+2)));
end;
end;
The answer is very simple. Each loop iteration will access 1 overlapping block in your image. All you have to do is count how many times the loop iterates, which is ((e-2) - 2 + 1) x ((f - 2) - 2 + 1) = (e - 3) x (f - 3). There's no need to keep a loop iteration variable.
Minor note. Under no circumstances should you use eval unless absolutely necessary. The MATLAB gods will smite any offenders swiftly. That code to assign a new variable to each increment of l is absolutely unnecessary. If you were to have 10000 overlapping blocks, you would have 10000 variables. You can just simply take a look at l at the end and this would tell you how many overlapping blocks you have.
Remove that line of code. WE HATES IT. IT BURNS US.
See this post by Loren Shure for more details on why using eval is bad.
For the 1-D case, the correct formula to estimate the total number of overlapping blocks is:
(#Of_blocks) = (#Image_width - #Block_width) / (#Block_width - #Block_overlap) + 1
If the result is not integer you just take the floor of #Of_blocks, this means that the whole interval can't be covered using that setup.
I have a n x 2 matrix in Octave, and I would like to find every row where the matrix(row, 1) and matrix(row, 2) elements are non-zero. I could use a for loop like this:
[nrows, ncols] = size(data);
for i = 1:nrows
if(data(i, 1) ~= 0 && data(i, 2) ~= 0)
% Do something
end
end
The issue with that is that n is about 3 million, and iteration in Octave takes for ever. I feel like there is a way to do it with find, but I haven't been able to figure it out yet.
Anyone have any advice?
Thanks!
You can create use logical indexing:
idx = all(data(:,1:2)~=0, 2);
The resulting vector idx contains 1s in every row where both cells are non-zero and 0 otherwise.
I think in this case (since it is related with zero values) the following also should work
idx=(data(:,1).*data(:,2)~=0)
But #H.Muster's solution is the one that works in all cases, hence a better one.
If performance is the issue: maybe try converting both columns to logical:
useful = and(logical(data(:,1)),logical(data(:,2)))
Then you can again use logical indexing:
filtered = data(useful,:)