Remove table rows based on condition in matlab - matlab

a=[1; 2 ; 3]; b=[ 4; 5; 6 ]; T=table(a,b).
I want to remove rows of table for which the value of b is less than or equal to 5 (b<=5).

You can use logical indexing:
a=[1; 2 ; 3];
b=[ 4; 5; 6 ];
T=table(a,b);
rowidx = (T.b <= 5);
T = T(~rowidx, :);
Which returns:
T =
1×2 table
a b
_ _
3 6

Fast, simple. elegant:
T(T.b <= 5,:) = [];

Another approach:
a = [1; 2; 3];
b = [4; 5; 6];
X = [a, b];
n = 1; m = 1;
while (n <= size(X, 1))
if(X(n, 2) > 5)
X_new(m, :) = X(n, :);
m = m + 1;
end
n = n + 1;
end
'X_new' will be the required matrix.

Related

How can I vectorize the following calculation?

Suppose there is a value n input from a user and it goes in to the following for loop code. Is there a way to vectorize the following code?
A = 1:n
B = [1 1;1 1]
for i = 1:n
B = B + A(i)*B;
end
Let's have a look at a specific example:
n = 5;
A = 1:n;
B = [1 1; 1 1];
for i = 1:n
B = B + A(i) * B;
end
B
The result is:
B =
720 720
720 720
First of all, I would re-write the loop:
n = 5;
A = 1:n;
B = [1 1; 1 1];
for i = 1:length(A)
B = B * (A(i) + 1);
end
B
That way, it's more obvious, that your loop variable i simply iterates all elements in A.
Also: B + A(i) * B is the same as B * (A(i) + 1).
Now, we see, that inside the loop, you're basically calculating:
B = B * (A(1) + 1) * (A(2) + 1) * (A(3) + 1) ...
The product over all elements in A (or here: A + 1) can be simplified by using MATLAB's prod function:
n = 5;
A = 1:n;
B = [1 1; 1 1];
B = B * prod(A + 1)
Let's check the result:
B =
720 720
720 720
In that very special case for A = 1:n, the product prod(A + 1) is simply the factorial of n + 1, such that we could also use MATLAB's factorial function:
n = 5;
B = [1 1; 1 1];
B = B * factorial(n + 1)

Dynamic window forming in efficient way in MATLAB

Can someone help me to provide an efficient way or help me to perform the provide code to do make same results in minimal possible steps. I shall be grateful to you.
I have an Original Array:
A = [1 1 1 4.3 4.5 4 4.3 3 1 0 0 2 6.2 6.3 6 6.2 7.4 8 7.2 2 2 3 3 2];
Output Looks like:
A = [1 1 1 4 4 4 4 3 1 0 0 2 6 6 6 6 6 7 7 2 2 3 3 2];
I apply some restrictions and removed some values from array of local maxima’s after that I received some new arrays.
Yposlocfiltered = [6 15 23];
idx = [4 6 3];
Yneglocfiltered = [2 9 20];
idx_neg = [1 1 2];
Where I will find idx(local maxima value) I will check if values behind and ahead are greater make a window.
Example
If I will find 4 and 4.5, 4.3 is greater than 4 include it in backward window
4.3 is greater than 4 include it in forward window.
I need to find range of values behind local maxima and ahead local maxima.
I have tried to write a code that’s works fine but issue is that it’s too long.
Can someone please provide me an idea to perform this action in minimal steps and in faster ways?
I have only provided code for positive local maxima’s as for negative local maxima code Is just replica of this.
Code:only for positive local maximas
clc
clear all
A = [1 0 1 4.3 4.5 5 4.3 3 0 0 0 2 6.2 6.3 7 6.2 7.4 8 7.2 1 2 3 4 2];
Yposlocfiltered = [ 6 15 23];
idx = [4 6 3];
Yneglocfiltered = [2 9 20];
idx_neg = [1 1 2];
for b = 1: numel(idx)
for c = 1:numel(A)
f = Yposlocfiltered(1,b)-c ;
g = Yposlocfiltered(1,b)+c ;
% if (f > 0 && g <= numel(X))
if(f > 0)
if (A(Yposlocfiltered(1,b)-c))> idx(1,b)
else
d= f+1;
z(b)= d;
backward_window = z;
break
end
end
end
end
for r = 1: numel(idx)
for s = 1:numel(A)
u = Yposlocfiltered(1,r)-s ;
v = Yposlocfiltered(1,r)+s ;
% if (f > 0 && g <= numel(X))
if(v <=numel(A))
if (A(Yposlocfiltered(1,r)+s))> idx(1,r)
else
w= v-1;
y(r)= w;
forward_window = y;
break
end
end
end
end
n=4
for i=1:length(backward_window)
range = backward_window(i): forward_window(i);
p = range
if n <= numel(p)
p = range(1:n)
A( p) = idx(i);
else
% if (size(range)<= 3)
A( p) = idx(i);
end
end
From the first look at your code, I believe you can combine your first two for loops into one.
sA = numel(A);
sI = numel(idx);
for i = 1:sI
f = Yposlocfiltered(i) - [1:sA];
g = Yposlocfiltered(i) + [1:sA];
f(f<1) = [];
g(g>sA) = [];
backward_window(i) = f(find(A(f) <= idx(i), 1)) + 1;
forward_window(i) = g(find(A(g) <= idx(i), 1)) - 1;
end
Here, you can use find to locate the element of an array matching the specified condition, i.e. g <= numel(X) or A(f) <= idx(i).
Your last loop which modifies A can also be integrated into the same loop, so you can have:
sA = numel(A);
sI = numel(idx);
n=4;
for i = 1:sI
f = Yposlocfiltered(i) - [1:sA];
g = Yposlocfiltered(i) + [1:sA];
f(f<1) = [];
g(g>sA) = [];
backward_window(i) = f(find(A(f) <= idx(i), 1)) + 1;
forward_window(i) = g(find(A(g) <= idx(i), 1)) - 1;
range = backward_window(i) : forward_window(i);
if n <= numel(range)
A(range(1:n)) = idx(i);
else
A(range) = idx(i);
end
end

Matrix Basis expansion

MATLAB:
I am trying to do basis expansion of a huge matrix(1000x15).
For example,
X =
x1 x2
1 4
2 5
3 6
I want to build a new matrix.
Y =
x1 x2 x1*x1 x1*x2 x2*x2
1 4 1 4 16
2 5 4 10 25
3 6 9 18 36
Could any one please suggest a easier way to do this
% your input
A = [1 4; 2 5; 3 6];
% generate pairs
[p,q] = meshgrid(1:size(A,2), 1:size(A,2));
% only retain unique pairs
ii = tril(p) > 0;
% perform element wise multiplication
res = [A A(:,p(ii)) .* A(:,q(ii))];
Using the one-liner from this answer to get the 2-combinations of the indices, you can generate the matrix without the interleaved ordering with
function Y = columnCombo(Y)
comb = nchoosek(1:size(Y,2),2);
Y = [Y , Y.^2 , Y(:,comb(:,1)).*Y(:,comb(:,2))];
end
For the interleaved ordering, I came up with this, possibly sub-optimal, solution:
function Y = columnCombo(Y)
[m,n] = size(Y);
comb = nchoosek(1:n,2);
Y = [Y,zeros(m,n + size(comb,1))];
col = n+1;
for k = 1:n-1
Y(:,col) = Y(:,k).*Y(:,k) ;
ms = comb(comb(:,1)==k,:) ;
ncol = size(ms,1) ;
Y(:,col+(1:ncol)) = Y(:,ms(:,1)).*Y(:,ms(:,2)) ;
col = col + ncol + 1 ;
end
Y(:,end) = Y(:,n).^2;
end

Replace rows having at least one duplicate number or one zero by a user defined row

I have a matrix having rows with repeated numbers.
A= [ 2 3 6;
4 7 4;
8 7 2;
1 3 1;
7 8 2 ]
The codes below find those rows and replace them with a Dummy_row [1 2 3]
new_A=[ 2 3 6;
1 2 3;
8 7 2;
1 2 3;
7 8 2 ]
This are the codes:
CODE NUMBER 1 (#Bruno)
Dummy_row = [1 2 3];
b = any(~diff(sort(A,2),1,2),2);
A(b,:) = repmat(Dummy_row,sum(b),1)
CODE NUMBER 2 (#Kamtal)
Dummy_row = [1 2 3];
b = diff(sort(A,2),1,2);
b = sum(b == 0,2);
b = b > 0;
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c
Note: both codes Number 1 and 2 perform the task efficiently.
Question
How can this code(either code num 1 or num 2) be modified such that it also replaces any rows having at least one zero with the Dummy_row?
Code 1
b = any(~diff(sort(A,2),1,2),2) | any(A==0,2); % <-- Only change
A(b,:) = repmat(Dummy_row,sum(b),1);
Code 2
b = diff(sort(A,2),1,2);
b = sum(b == 0,2);
b = (b > 0) | any(A==0,2); % <-- Only change
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c;
By the way: Code1 basically does the same thing that Code2 does, just that it uses logical-indexing instead of doing the unnecessary conversion from logical indexes to index positions.

MATLAB bsxfun or vectorization

I have been working on vectorizing my code mostly using bsxfun, but I came across a scenario that I can't quite crack. Here is a small sample of problem. I would like to remove the for loops in this code, but I am having a hard time with the tempEA line.
Index = [2; 3; 4;];
dTime = [25; 26; 27; 28; 25; 26; 27; 28; 27; 28];
dIndex = [3; 3; 3; 2; 1; 3; 2; 4; 4; 2];
aTime = [30; 38; 34; 39; 30; 38; 34; 39; 34; 39];
aIndex = [4; 2; 5; 4; 5; 4; 4; 2; 2; 4];
EA = zeros(numel(Index));
for i = 1:numel(Index)
for j = 1:numel(Index)
tempEA = aTime(Index(i) == dIndex(:,1) & Index(j) == aIndex(:,1));
if i == j
elseif tempEA > 0
EA(i,j) = min(tempEA);
else
EA(i,j) = 50;
end
end
end
The answer should look like this:
EA =
0 50 34
38 0 30
34 50 0
Thanks for help in advance.
This uses bsxfun; no loops. It assumes you don't have NaN's among your aTimevalues.
N = numel(Index);
ii = bsxfun(#eq, dIndex.', Index); %'// selected values according to each i
jj = bsxfun(#eq, aIndex.', Index); %'// selected values according to each j
[ igrid jgrid ] = ndgrid(1:N); %// generate all combinations of i and j
match = double(ii(igrid(:),:) & jj(jgrid(:),:)); %// each row contains the matches for an (i,j) combination
match(~match) = NaN; %// these entries will not be considered when minimizing
result = min(bsxfun(#times, aTime, match.')); %'// minimize according to each row of "match"
result = reshape(result,[N N]);
result(isnan(result)) = 50; %// set NaN to 50
result(result<=0) = 50; %// set nonpositive values to 50
result(1:N+1:end) = 0; %// set diagonal to 0
The line result(result<=0) = 50; is only necessary if your aTime can contain nonpositive values. Can it? Or is your elseif tempEA > 0 just a way of checking that tempEA is not empty?