remove rows of matrix in matlab - matlab

If I have a matrix X with only one column and it has some negative values in some rows. How can I remove only the negative values?
Example:
X=[-1; 2; 3; -4; 5]
should become:
X=[2; 3; 5]
Also, how can I remove values from
y=[1; 2; 3; 4; 5]
based on where the negative values in X are found? y should be [2; 3; 5] after this operation.

Removing negative values from X:
You can either reassign X to a vector which only contains the values of X which are not negative:
>> X = X(X>=0)
X =
2
3
5
or delete the negative values from X:
>> X(X<0) = []
X =
2
3
5
Removing values from y based on the indices of negative values in X is similar. Either reassign:
>> y = y(X>=0)
y =
2
3
5
Or delete:
>> y(X<0) = []
y =
2
3
5
If you want to modify both vectors based on the negative values in X remember to do the operation to y first or store a logical vector for the positions where X<0. For example:
>> ind = X < 0;
>> X(ind) = []
X =
2
3
5
>> y(ind) = []
y =
2
3
5

Related

How to save indices and values from Matrix in Matlab?

I have a 3x3 Matrix and want to save the indices and values into a new 9x3 matrix. For example A = [1 2 3 ; 4 5 6 ; 7 8 9] so that I will get a matrix x = [1 1 1; 1 2 2; 1 3 3; 2 1 4; 2 2 5; ...] With my code I only be able to store the last values x = [3 3 9].
A = [1 2 3 ; 4 5 6 ; 7 8 9];
x=[];
for i = 1:size(A)
for j = 1:size(A)
x =[i j A(i,j)]
end
end
Thanks for your help
Vectorized approach
Here's one way to do it that avoids loops:
A = [1 2 3 ; 4 5 6 ; 7 8 9];
[ii, jj] = ndgrid(1:size(A,1), 1:size(A,2)); % row and column indices
vv = A.'; % values. Transpose because column changes first in the result, then row
x = [jj(:) ii(:) vv(:)]; % result
Using your code
You're only missing concatenation with previous x:
A = [1 2 3 ; 4 5 6 ; 7 8 9];
x = [];
for i = 1:size(A)
for j = 1:size(A)
x = [x; i j A(i,j)]; % concatenate new row to previous x
end
end
Two additional suggestions:
Don't use i and j as variable names, because that shadows the imaginary unit.
Preallocate x instead of having it grow in each iteration, to increase speed.
The modified code is:
A = [1 2 3 ; 4 5 6 ; 7 8 9];
x = NaN(numel(A),3); % preallocate
n = 0;
for ii = 1:size(A)
for jj = 1:size(A)
n = n + 1; % update row counter
x(n,:) = [ii jj A(ii,jj)]; % fill row n
end
end
I developed a solution that works much faster. Here is the code:
% Generate subscripts from linear index
[i, j] = ind2sub(size(A),1:numel(A));
% Just concatenate subscripts and values
x = [i' j' A(:)];
Try it out and let me know ;)

adding consecutive numbers in a vector in matlab

i have a vector and a scalar as input in a problem , the problem is to compute the largest product of n consecutive number of the vector and output the product and the index of the element of the vector that is the first term of the product.
E.g vector =[ 1 2 3 4 5 6] , n=3
I'm supposed to get '3' (i e n) consecutive number of vector whose product is the largest .
in this case it will be 4*5*6
so output will be 120 and 4 as the index.
now if vector has fewer than 'n' elements, the function outputon returns 0 and -1 as the output.
please i need ideas on how to achieve this
You can make a simple implementation with loops:
a = [1 2 3 4 5 6]
w = 3
n = length(a)
maximum = -1
for i = 1:n-w
p = prod(a(i:i+w))
if (p > maximum)
maximum = p
end
end
maximum
Or, you can use the nlfilter from the image processing palette.
a = []
w = 3
if (length(a) >= w)
products = nlfilter(a, [1 w], #(x) prod(x))
res = max(products)
else
res = -1
end
You can create the moving window from the answer of raryeng for the question Matrix with sliding window elements and then appyl cumprod on the columns and take the max with its index.
myvec = [1 2 2 1 3 1];
n = 3;
ind = bsxfun(#plus, 1:n, (0:1:length(myvec)-n).')';
M = cumprod(myvec(ind));
[val,its_ind] = max(M(end,:));
You can encapsulate this with an if condition checking whether the length of myvec is larger than
You can compute the element-wise logarithm of your vector, so multiplication becomes addition; and sliding addition is just convolution with a window of ones:
function [m, p] = f(v, n)
if numel(v) < n
m = -1;
p = 0;
else
c = conv(log(v(:)), ones(n,1), 'valid'); % convolution with vector of n ones
[~, m] = max(c); % starting index of maximizing window
p = prod(v(m+(0:n-1))); % corresponding product
end
Examples:
>> v = [1 2 3 4 5 6]; n = 3;
>> [m, p] = f(v,n)
m =
4
p =
120
>> v = [1 2 3 4 5 6]; n = 7;
>> [m, p] = f(v,n)
m =
-1
p =
0
>> v = [1 4 6 2 5 3]; n = 3;
>> [m, p] = f(v,n)
m =
3
p =
60

Rotate the rows of a matrix (like GAUSS function rotater)

I'm currently bringing some GAUSS code over to Matlab and I'm stuck trying to use the GAUSS "rotater" function.
The command reference entry for rotater says:
Purpose Rotates the rows of a matrix
Format y = rotater(x,r)
Input x: N x K matrix to be rotated. r: N x 1 or 1 x 1 matrix specifying the amount of rotation.
Output y: N x K rotated matrix.
Remarks The rotation is performed horizontally within each row of the matrix. A positive rotation value will cause the elements to move
to the right. A negative rotation will cause the elements to move to
the left. In either case, the elements that are pushed off the end of
the row will wrap around to the opposite end of the same row. If the rotation value is greater than or equal to the number of columns in x, then the rotation value will be calculated using (r % cols(x)).
Example 1
(I'm following Matlab's notation here, with straight brackets for matrices and a semicolon for a new ro)
If x = [1 2 3; 4 5 6], and r = [1; -1],then y = [3 1 2; 5 6 4]
Example 1
If x = [1 2 3; 4 5 6; 7 8 9; 10, 11, 12], and r = [0; 1; 2; 3], then y = [1 2 3; 6 4 5; 8 9 7; 10 11 12]
Maybe someone has found a function like that somewhere or can give me advice how to write it?
This can be done using bsxfun twice:
Compute rotated row indices by subtracting r with bsxfun and using mod. As usual, mod needs indices starting at 0, not 1. The rotated row indices are left as 0-based, because that's more convenient for step 2.
Get a linear index from columns and rotated rows, again using bsxfun. This linear index applied to x gives y:
Code:
[s1 s2] = size(x);
rows = mod(bsxfun(#plus, 1:s2, -r(:))-1, s2); % // step 1
y = x(bsxfun(#plus, rows*s1, (1:s1).')); %'// step 2
circshift is pretty close to what you're looking for except that 1) it works on columns rather than rows, and 2) it shifts the entire matrix by the same offset.
The first one is easy to fix, we just transpose. For the second one I haven't been able to find a vectorized approach, but in the meantime, here's a version with a for loop:
x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
r = [0 1 2 3]
B = x'
C = zeros(size(B));
for ii = 1:size(B,2)
C(:,ii) = circshift(B(:,ii),r(ii));
end
y = C'
The output is:
x =
1 2 3
4 5 6
7 8 9
10 11 12
r =
0 1 2 3
B =
1 4 7 10
2 5 8 11
3 6 9 12
y =
1 2 3
6 4 5
8 9 7
10 11 12
This can be done using a simple for loop to iterate over each row, and a function called 'circshift' from matlab.
I created a function the goes through each row and applies the appropriate shift to it. There may be more efficient ways to implement this, but this way works with your examples. I created a function
function rotated_arr = GaussRotate(input_array, rotation_vector)
[N,K] = size(input_array)
%creates array for return values
rotated_arr = zeros(N,K);
%if the rotation vector is a scalar
if (length(rotation_vector) == 1)
%replicate the value once for each row
rotation_vector = repmat(rotation_vector, [1,N]);
end
%if the rotation vector doesn't have as many entries as there are rows
%in the input array
if (length(rotation_vector) ~= N)
disp('ERROR GaussRotate: rotation_vector is the wrong size')
disp('if input_Array is NxK, rotation_vector must be Nx1 or 1x1')
return
end
%for each row
for idx=1:size(input_array,1)
%shift the row by the appropriate number of columns
%we use [0,shift] because we want to shift the columns, the row
%stays where it is (even though this is a 1xN at this point we
%still specify rows vs columns)
rotated_arr(idx,:) = circshift(input_array(idx,:),[0,rotation_vector(idx)]);
end
end
then simply called it with your examples
x = [1 2 3; 4 5 6];
r = [1; -1];
y = GaussRotate(x,r)
%produces [3 1 2; 5 6 4]
%I also made it support the 1x1 case
r = [-1]
%this will shift all elements one column to the left
y = GaussRotate(x,r)
%produces [2 3 1; 5 6 4]
x = [1 2 3; 4 5 6; 7 8 9; 10, 11, 12]
r = [0; 1; 2; 3]
y = GaussRotate(x,r)
%produces [1 2 3; 6 4 5; 8 9 7; 10 11 12]

sum in multidimensional arrays matlab

I have an I x K x V array, where V = S x R, ie, the third dimension has "S" observation for "R" different categories. I would like to end up with an I x K x S that has, in the third dimension, the sum across R within each S.
e,g: I = 3, K = 3, S=2 and R=2, I want to end up with a matrix C that is 3x3x2 that sums the third dimension in the following way.
A = [5 7 8; 0 1 9;4 3 6];
A(:,:,2)=[1 0 4; 3 5 6;9 8 7]
A(:,:,3)=[3 2 1 ; 4 5 6; 3 4 5]
A(:,:,4)=[1 2 3 ; 3 4 5; 5 6 7]
C=A(:,:,1)+A(:,:,2)
C2=A(:,:,3)+A(:,:,4)
C(:,:,2)=C2
I cannot do this manually b/c R and S are very large in my "real" case.
Thanks!
Separate the S and R dimensions with reshape, and then sum across the third dimension, which is S:
I = 3; K = 3; S = 2; R = 2;
C = squeeze(sum(reshape(A,[I K S R]),3));
If you want to sum across R, that's the fourth dimension:
C = sum(reshape(A,[I K S R]),4);

Find the minimum positive difference between elements in vector

A = [1 3 5 8]
B = [1 2 3 4 5 6 7 8]
I would like to create a vector C which returns the rownumber of the element in vector A with the smallest non-negative difference to each element in vector B.
So, given the example above, it should return:
C = [1 2 2 3 3 4 4 4]
I'm sure there are many ways to do this. Here's one:
A = [1 3 5 8]
B = [1 2 3 4 5 6 7 8]
%create matrices of the values to subtract
[a,b] = meshgrid(A,B);
%subtract
aLessB = a-b;
%make sure we don't use the negative values
aLessB(aLessB < 0) = Inf;
%sort the subtracted matrix
[dum, idx] = sort(aLessB, 2, 'ascend');
idx(:,1) is the solution you are looking for.
An alternative solution:
D = bsxfun(#minus, A', B);
D(D < 0) = Inf;
[~, C] = min(D, [], 1);