How can I iterate over matrix and change values under condition.. for e.g:
I have matrix m with size 100x100 and Im doing:
m(m<10)=func(elemnt);
element should be the current element at iteration.. How do I access the current element??
Try simply
m(m<10)=func(m(m<10));
example:
m=[[1 2 3];[5 6 7];[8 9 10]]
m =
1 2 3
5 6 7
8 9 10
m(mod(m,3)==2) = m(mod(m,3)==2) * 5
m =
1 10 3
25 6 7
40 9 10
The only constraint is that your custom function can handle vectors.
Related
Is there any command to find mean of first 5 values then next 5 values from a total of 25 values present in a vector in MATLAB. If the dataset is X.
If anyone can help me to provide a code where I can get mean at every 5th value.
X=[4 5 6 7 2 5 7 4 2 6 7 3 2 1 5 7 8 3 4 6 8 4 2 6 8];
You can for instance reshape the vector in an array with reshape and then apply the mean function:
M = mean(reshape(X, [5, numel(X)/5]),1);
or simply
M = mean(reshape(X, 5, []),1);
But there as stated in the comments there are many other ways.
Here is one simple way to do it. Rearrange the vector into a matrix loop over the columns and take the mean of all values in each column. Store the results in a new vector.
X=[4 5 6 7 2 5 7 4 2 6 7 3 2 1 5 7 8 3 4 6 8 4 2 6 8];
Xr = reshape(X,5,5)
cols = size(Xr)(2)
avgs=zeros(1,cols)
for i= 1:cols
avgs(i) = mean(Xr(:,i))
end
I have a 4x9 matrix, and I need to calculate the sum of all numbers in every other column of c starting with the first. Can anyone point me in the right direction? I know we have to use the function sum() but that's about it.
I used Octave rather than MATLAB, but this works for me:
A = randi(10,4,9)
B = A(:, 1:2:9)
C = sum(B)
Generate a 4x9 matrix with random numbers between 1 and 10, then create a sub-matrix with each row, and given columns 1:2:9 means starting from the first column and ending on the 9th, choose every second column, then sum up each column. Example output:
>> A = randi(10,4,9)
A =
1 3 6 8 2 8 4 8 10
3 6 10 4 6 4 6 2 8
4 3 9 2 7 10 6 9 6
8 5 3 9 3 8 4 6 10
>> B = A(:, 1:2:9)
B =
1 6 2 4 10
3 10 6 6 8
4 9 7 6 6
8 3 3 4 10
>> C = sum(B)
C =
16 28 18 20 34
You could also take the sum of matrix C using the sum() first and then select every other element from the result starting from the 1st element.
tmpC = sum(C);
result = tmpC(1:2:end)
How do I rotate a matrix to create a spiral order of values?
For example,
12 4 2
8 3 11
6 7 2
I am supposed to to display 12 4 2 11 2 7 6 8 3 but I don't know how to terminate at the 1st row and rotate the function 90 degrees. Thanks in advance for the help.
Hint:
Check the spiral function:
spiral(n) is an n-by-n matrix with elements ranging
from 1 to n^2 in a rectangular spiral pattern.
Use its output to build an index into the original values. You may also need sort, as well as fliplr to reverse the order of values.
See the code after you've given it a try.
x = [12 4 2; 8 3 11; 6 7 2];
t = fliplr(spiral(sqrt(numel(x))));
[~, ind] = sort(t(:));
result = fliplr(x(ind).');
A =[12 4 2;...
8 3 11;...
6 7 2];
B=[];
for ii=1:5
B = [B A(1,:)];
A(1,:)=[];
A=rot90(A);
end
B
B =
12 4 2 11 2 7 6 8 3
I've a vector that I would like to split into overlapping subvectors of size cs in shifts of sh. Imagine the input vector is:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
given a chunksize of 4 (cs=4) and shift of 2 (sh=2), the result should look like:
[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]
note that the input vector is not necessarily divisible by the chunksize and therefore some subvectors are discarded. Is there any fast way to compute that, without the need of using e.g. a for loop?
In a related post I found how to do that but when considering non-overlapping subvectors.
You can use the function bsxfun in the following manner:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
A = v(bsxfun(#plus,(1:cs),(0:sh:length(v)-cs)'));
Here is how it works. bsxfun applies some basic functions on 2 arrays and performs some repmat-like if the sizes of inputs do not fit. In this case, I generate the indexes of the first chunk, and add the offset of each chunck. As one input is a row-vector and the other is a column-vector, the result is a matrix. Finally, when indexing a vector with a matrix, the result is a matrix, that is precisely what you expect.
And it is a one-liner, (almost) always fun :).
Do you have the signal processing toolbox? Then the command is buffer. First look at the bare output:
buffer(v, 4, 2)
ans =
0 1 3 5 7 9 11
0 2 4 6 8 10 12
1 3 5 7 9 11 13
2 4 6 8 10 12 0
That's clearly the right idea, with only a little tuning necessary to give you exactly the output you want:
[y z] = buffer(v, 4, 2, 'nodelay');
y.'
ans =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
That said, consider leaving the vectors columnwise, as that better matches most use cases. For example, the mean of each window is just mean of the matrix, as columnwise is the default.
I suppose the simplest way is actually with a loop.
A vectorizes solution can be faster, but if the result is properly preallocated the loop should perform decently as well.
v = 1:13
cs = 4;
sh = 2;
myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;
for t = cs:sh:numel(v)
count = count+1;
myMat(count,:) = v(t-cs+1:t);
end
You can accomplish this with ndgrid:
>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
The nice thing about the second syntax of the colon operator (j:i:k) is that you don't have to calculate k exactly (e.g. 1:2:6 gives [1 3 5]) if you plan to discard the extra entries, as in this problem. It automatically goes to j+m*i, where m = fix((k-j)/i);
Different test:
>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
And a new row will form with v=1:17. Does this handle all cases as needed?
What about this? First I generate the starting-indices based on cs and sh for slicing the single vectors out of the full-length vector, then I delete all indices for which idx+cs would exceed the vector length and then I'm slicing out the single sub-vectors via arrayfun and afterwards converting them into a matrix:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(#(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')
E.g. for cs=5; sh=3; this would give:
idx =
1 3 5 7
ans =
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 10 11
Depending on where the values cs; sh come from, you'd probably want to introduce a simple error-check so that cs > 0; as well as sh < cs. sh < 0 would be possible theoretically if you'd want to leave some values out in between.
EDIT: Fixed a very small bug, should be running for different combinations of sh and cs now.
Suppose I have two matrices p
p =
1 3 6 7 3 6
8 5 10 10 10 4
5 4 8 9 1 7
5 5 5 3 8 9
9 3 5 4 3 1
3 3 9 10 4 1
then after sorting the columns of matrix p into ascending order
y =
1 3 5 3 1 1
3 3 5 4 3 1
5 3 6 7 3 4
5 4 8 9 4 6
8 5 9 10 8 7
9 5 10 10 10 9
I want to know, given a value from y, what its row was in p
ex: the value 3 which is in matrix p located in row 6 column 1
then after sorting it located in matrix y in row 2 column 1
So I want at the end the values after sorting in matrix y, where it was originally in matrix p
Just use second output of sort:
[y ind] = sort(p);
Your desired result (original row of each value) is in matrix ind.
The Matlab sort command returns a second value which can be used to index into the original array or matrix. From the sort documentation:
[Y,I] = sort(X,DIM,MODE) also returns an index matrix I.
If X is a vector, then Y = X(I).
If X is an m-by-n matrix and DIM=1, then
for j = 1:n, Y(:,j) = X(I(:,j),j); end
Ok i understand exactly what you want.
I will give you my code that i write now, it is not optimal but you can optimize it or i can work with you in order to get the better code..
P and y have the same size.
[n,m]=size(p);
for L=1:m
i=1;
temp=y(i,L);
while(i<=n)
if(temp==y(i,L))
% So it is present in case i of p
disp(['It is present in line' num2str(i) ' of p']);
end
i=i+1;
end
end
VoilĂ !!