Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to extract rows from matrix based on value in first entry?

This is another simple 'matrix' question in Mathematica. I want to show how I did this, and ask if there is a better answer.

I want to select all 'rows' from matrix based on value in the first column (or any column, I used first column here just as an example).

Say, find all rows where the entry in the first position is <=4 in this example:

    list = {{1, 2, 3},
           {4, 5, 8},
           {7 , 8, 9}}

So, the result should be

            {{1,2,3},
             {4,5,8}}

Well, the problem is I need to use Position, since the result returned by Position can be used directly by Extract. (but can't be used by Part or [[ ]], so that is why I am just looking at Position[] ).

But I do not know how to tell Position to please restrict the 'search' pattern to only the 'first' column so I can do this in one line.

When I type

pos = Position[list, _?(# <= 4 &)]

it returns position of ALL entries which are <=4.

{{1, 1}, {1, 2}, {1, 3}, {2, 1}}

If I first get the first column, then apply Position on it, it works ofcourse

  list = {{1, 2, 3},
          {4, 5, 8},
          {7 , 8, 9}};
   pos = Position[list[[All, 1]], _?(# <= 4 &)]
   Extract[list, pos]
   -->       {{1, 2, 3}, {4, 5, 8}}

Also I tried this:

pos = Position[list, _?(# <= 4 &)];
pos = Select[pos, #[[2]] == 1 &]  (*only look at ones in the 'first' column*)

{{1, 1}, {2, 1}}---> 

and this gives me the correct positions in the first column. To use that to find all rows, I did

pos = pos[[All, 1]] (* to get list of row positions*)
---> {1, 2}

list[[ pos[[1]] ;; pos[[-1]], All]]
{{1, 2, 3}, 
 {4, 5, 8}}

So, to summarize, putting it all together, this is what I did:

method 1

 list = {{1, 2, 3},
         {4, 5, 8},
         {7 , 8, 9}};
 pos = Position[list[[All, 1]], _?(# <= 4 &)]
 Extract[list, pos]
  -->       {{1, 2, 3}, {4, 5, 8}}

method 2

list = {{1, 2, 3},
      {4, 5, 8},
      {7 , 8, 9}}

pos = Position[list, _?(# <= 4 &)];
pos = Select[pos, #[[2]] == 1 &];
pos = pos[[All, 1]];
list[[ pos[[1]] ;; pos[[-1]], All]]

{{1, 2, 3}, 
{4, 5, 8}}

 The above clearly is not too good. 

Is method 1 above the 'correct' functional way to do this?

For reference, this is how I do the above in Matlab:

EDU>> A=[1 2 3;4 5 8;7 8 9]
A =
     1     2     3
     4     5     8
     7     8     9

EDU>> A( A(:,1)<=4 , :)

     1     2     3
     4     5     8

I am trying to improve my 'functional' handling of working with matrices in Mathematica commands, this is an area I feel I am not good at working with lists. I find working with matrices easier for me.

The question is: Is there is a shorter/more functional way to do this in Mathematica?

thanks

like image 488
Nasser Avatar asked Nov 30 '22 16:11

Nasser


2 Answers

You could use Pick[] as follows:

Pick[list, list[[All, 1]], _?(# <= 4 &)]
like image 143
Asim Avatar answered Dec 05 '22 06:12

Asim


How about the following?

In[1]:= list = {{1, 2, 3}, {4, 5, 8}, {7, 8, 9}};

In[2]:= Select[list, First[#] <= 4 &]

Out[2]= {{1, 2, 3}, {4, 5, 8}}

Here's a loose translation of your matlab code:

list[[Flatten[Position[Thread[list[[All, 1]] <= 4], True]]]]

(of course, the Flatten would not be needed if I used Extract instead of Part).

like image 43
Simon Avatar answered Dec 05 '22 06:12

Simon