3

Given: square matrix, and list which represents the index of rows to be removed, and it also represent at the same time the index of the columns to be removed (it is square matrix, so only one list is needed).

output: the square matrix, with BOTH the rows and the columns columns in the list removed.

Assume valid list of indices.

This is an example enter image description here

So the above says to remove the second and the 4th rows, and also the second and the 4th column.

I could not figure how to use Delete[] to remove both rows and columns at the same time, and I really did not want to make a list of each individual element index I want to remove.

But I could use Delete to remove rows.

This below how I solved it, I removed the rows first, then transposed the matrix, and then removed the rows of the new matrix (which will be the columns of the original), then transposed the result back to obtain what I wanted.

like this:

a = {{0, 5, 2, 3, 1, 0}, {4, 3, 2, 5, 1, 3}, {4, 1, 3, 5, 3, 2}, {4, 
    4, 1, 1, 1, 5}, {3, 4, 4, 5, 3, 3}, {5, 1, 4, 5, 2, 0}};
del = {{2}, {4}};
a = Delete[a, del];
a = Delete[Transpose[a], del];
(a = Transpose[a]) // MatrixForm

my question: Is there a shorter way using Delete (or another one of those expert tricks) to do this in a better way ?

thanks

Nasser
  • 12,849
  • 6
  • 52
  • 104
  • 2
    Duplicate of this question: http://stackoverflow.com/questions/6258349/how-to-form-submatrices-with-some-non-consecutive-rows-and-columns-of-a-matrix . Voting to close – Leonid Shifrin Jan 06 '12 at 09:41
  • Similar question here: http://stackoverflow.com/questions/7537401/how-to-insert-a-column-into-a-matrix-the-correct-mathematica-way/7537692#7537692 – Chris Degnen Jan 06 '12 at 10:45
  • 2
    [This](http://stackoverflow.com/q/5299798/499167) question, **Efficient way to pick/delete a list of rows/columns in a matrix in Mathematica**, is also related, in particular the [reply](http://stackoverflow.com/a/5300892/499167) by WReach – 681234 Jan 06 '12 at 10:48

4 Answers4

7

In cases where you want to remove the same indexed columns and rows I would use Part. For example to see a with columns and rows 2 and 4 removed:

a[[{1, 3, 5, 6}, {1, 3, 5, 6}]] // MatrixForm

To make it more general you could create something in which you combine DeleteCases with Range and the list of column/row indexes but in the absence of further information I haven't tried to do that (yet).

Edit

remove[a_?MatrixQ, pos_List] := Module[{tmp, length = Length[a]},

  tmp = DeleteCases[Range[length], Alternatives @@ pos];

  a[[tmp, tmp]]

  ]

remove[a,{2,4}]
{{0, 2, 1, 0}, {4, 3, 3, 2}, {3, 4, 3, 3}, {5, 4, 2, 0}}

Edit2

remove2[a_?MatrixQ, pos_List] := Module[{tmp, length = Length[a]},

  tmp = Complement[Range[length], pos];

  a[[tmp, tmp]]

  ]

remove2[a,{2,4}]
{{0, 2, 1, 0}, {4, 3, 3, 2}, {3, 4, 3, 3}, {5, 4, 2, 0}}

test both of these for your real world problem.

Mike Honeychurch
  • 1,683
  • 10
  • 17
  • Yes, that is better. I was fixated on using `Delete` since what I generated is a list of rows/cols to delete. But I can easily complement this list to obtain the list of rows not to delete, and then use `Part` as you showed. This seems to be a good solution. Much better than what I have. I think I need more coffee, because I should have thought of this :) – Nasser Jan 06 '12 at 06:01
  • might be little simpler to use `Complement[length, pos]` in the above instead of `DeleteCases[Range[length], Alternatives @@ pos]` – Nasser Jan 06 '12 at 06:18
  • 1
    Depends on list length I think but you can compare some timings for your real world problem and see what is best. – Mike Honeychurch Jan 06 '12 at 06:23
  • opps, I meant to write above `Complement[Range[length], pos]` ofcourse. (hard to write code in such small window) – Nasser Jan 06 '12 at 07:50
4

This should be a faster way to delete rows than the double transpose method:

a = {{0, 5, 2, 3, 1, 0},
     {4, 3, 2, 5, 1, 3},
     {4, 1, 3, 5, 3, 2},
     {4, 4, 1, 1, 1, 5},
     {3, 4, 4, 5, 3, 3},
     {5, 1, 4, 5, 2, 0}};
del = {{2}, {4}};

a = MapThread[Delete, {a, Table[del, {Length[a]}]}]

Timing varies, but in this somewhat contrived example it is faster:

a = Table[RandomReal[], {1000}, {10000}];
del = Map[List, Union[Table[RandomInteger[{1, 10000}], {100}]]];
Timing[Transpose[Delete[Transpose[a], del]];]

{0.25, Null}

Timing[MapThread[Delete, {a, Table[del, {Length[a]}]}];]

(0.125, Null}

Chris Degnen
  • 8,443
  • 2
  • 23
  • 40
  • Hello Chris, we have a proposal for a [separate Mathematica site](http://area51.stackexchange.com/proposals/37304/mathematica?referrer=hWeRiD9Qz0oIDM_9uBjtlA2) under the SE network, for anything related to mma (not just programming questions like on SO). We're very close to launching (24 users remaining) and it would be great if you could commit to that proposal :) – abcd Jan 10 '12 at 05:31
1

This is much less efficient than the Part method, but I find it somewhat more transparent, and there are times that matters more.

ReplacePart[a, {{2}, {4}, {_, 2}, {_, 4}} :> Sequence[]]
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
  • +1, nice. too bad can't just write `Delete[a, {{2}, {4}, {_, 2}, {_, 4}}]` like that. But your trick of using `:> Sequence[]` to replace those parts with is something I would not thought of. I still not sure how it works, but it does. I also think your solution is more natural. Many Mathematica commands, and many ways to use them ! I think I'll add your method to my list of cheat sheet for working with matrices in Mathematica. – Nasser Jan 13 '12 at 20:08
  • btw, even though this method is more natural, I think for automation it seems little hard to use? would needs more code. The reason is that the list of rows/column to keep (or delete by complementing) can be long and generated on the fly as part of running code. Hence to use the above method, one needs to write additional code to generate the `{{n1},{n2}...},{_,n1},{_n2}}...}` part of the command as the list involved will be a variable. thanks – Nasser Jan 13 '12 at 21:10
0

You can certainly do your example with Drop:

Drop[a, {2, 4, 2}, {2, 4, 2}] // MatrixForm

I don't know how general this is, but maybe it will help set you off in the right direction.

Tim Mayes
  • 554
  • 3
  • 9
  • thanks, but the above does not work. You are using the 'in steps on 2' option. This is very specific for this example, it works, but it needs to work on a list of rows/column, and it might not always happen to be by steps of 2 or such. What I have is just an example. – Nasser Jan 06 '12 at 05:53
  • @Nasser, I figured as much, thus the qualifier. – Tim Mayes Jan 06 '12 at 05:58