Khurram Majeed
Khurram Majeed

Reputation: 2411

Extract positive and negative vales from Matrix

I have 3D matrix like this

1   5648.00278672228    -46.43159546036
1   5650.38906894239    68.81787768047
1   5649.13081105839    -4867.55961979647
1   5650.53055771227    4868.95936645035
1   5647.95215053492    4866.38095927300
1   5650.21656586142    -2328.64537459950
1   5651.76371933598    7870.19252807406
1   5649.87288540620    -1168.30169414428

and I want to extract positive and negative values of 3rd column into two seperate 2D matrices (POS and NEG) where 1st column contains the index of the row from the above matrix, and second column contains the value.

The result should look like

POS = 
2   68.81787768047
4   4868.95936645035
5   4866.38095927300
7   7870.19252807406

and

NEG =  
1   -46.43159546036
3   -4867.55961979647
6   -2328.64537459950
8   -1168.30169414428

Upvotes: 2

Views: 6290

Answers (3)

Rody Oldenhuis
Rody Oldenhuis

Reputation: 38052

Here is yet another way:

B = [(1:size(A,1)).' A(:,3)];
inds = B(:,2)>0;
POS = B( inds,:);
NEG = B(~inds,:);

This is faster than Magla's find solution:

tic
for ii = 1:1e5
    B = [(1:size(A,1)).' A(:,3)];
    inds = B(:,2)>0;
    POS = B( inds,:);
    NEG = B(~inds,:);
end
toc

tic
for ii = 1:1e5
    POS = [find(A(:,3)>0) A(A(:,3)>0,3)];
    NEG = [find(A(:,3)<=0) A(A(:,3)<=0,3)];
end
toc

Results on my crappy machine:

Elapsed time is 1.290744 seconds. % my new solution
Elapsed time is 2.004015 seconds. % Magla's solution w/ find()

This difference is partly due to skipping find, negating the logical indices instead of comparing again to <= 0, and re-using the indices instead of re-computing them.

Even compared to a more optimal version of Magla's solution:

tic
for ii = 1:1e5
    inds = A(:,3)>0;
    POS = [find( inds) A( inds,3)];
    NEG = [find(~inds) A(~inds,3)];
end
toc

we find

Elapsed time is 1.290744 seconds. % my new solution
Elapsed time is 1.476138 seconds. % Magla's solution w/ find()

Upvotes: 3

marsei
marsei

Reputation: 7751

You may use the find function and logical indexing

POS = [find(A(:,3)>0) A(A(:,3)>0,3)]
NEG = [find(A(:,3)<=0) A(A(:,3)<=0,3)]

For your input matrix being A

A = [1   5648.00278672228    -46.43159546036
    1   5650.38906894239    68.81787768047
    1   5649.13081105839    -4867.55961979647
    1   5650.53055771227    4868.95936645035
    1   5647.95215053492    4866.38095927300
    1   5650.21656586142    -2328.64537459950
    1   5651.76371933598    7870.19252807406
    1   5649.87288540620    -1168.30169414428]

the results will be (with format shortG)

POS =

        2       68.818
        4         4869
        5       4866.4
        7       7870.2


NEG =

        1      -46.432
        3      -4867.6
        6      -2328.6
        8      -1168.3

the second find was removed thanks to @Dennis Jaheruddin and Khurram Majeed' comments.

Upvotes: 3

Dennis Jaheruddin
Dennis Jaheruddin

Reputation: 21561

Here is an alternate way to do it

p = find(A(:,3)>0);
n = find(A(:,3)<0);

POS = [p A(p,3)]
NEG = [n A(n,3)]

Note that this does not include zero entries. If you want them in the first vector for example use >= instead of >.

Upvotes: 3

Related Questions