4

This question is in a way a continuation of the question I asked here:Simple way to delete a matrix column in Mathematica to which @belisarius and @Daniel provided very helpful answers.

What I am generally trying to do is to extract from a matrix A specific lines and columns OR what remains after what those specified are removed. So this can be formally writtewn as, find TakeOperator and Drop Operator such that:

TakeOperator[A,{i1,..,ip},{j1,...,jq}]=(A[[ik]][[jl]]) (1<=k<=p, 1<=l<=q) =Table[A[[ik]][[jl]],{k,p},{l,q}]

We note Ic={i'1,...,i'p'}=Complement[{1,...,Length[A]},{i1,...,ip}];Jc={j'1,...,j'q'}=Complement[{1,...,Length[A]},{j1,...,jq}];

DropOperator[A,{i1,..,ip},{j1,...,jq}]=(A[[ik]][[jl]]) (1<=k'<=p', 1<=l'<=q') =Table[A[[ik']][[jl']],{k',p'},{l','q}]

While Table as described above does the trick, it is highly inefficient to use Table in that manner.

Just to give an idea, I took @ belisarius example:

In: First@Timing[a = RandomInteger[1000, {5000, 5000}];]

Out:0.218

In:Clear[b,c]

In:First@Timing[
  b = Table[
    If[i < 100, If[j < 100, a[[i]][[j]], a[[i]][[j + 1]]], 
     If[j < 100, a[[i + 1]][[j]], a[[i + 1]][[j + 1]]]], {i, 
     4999}, {j, 4999}]]

Out:140.807

In:First@Timing[c = Drop[a, {100}, {100}]]

Out:0.093

In:c===b

Out:True

Note: With respect to the use of Drop in the earlier post, I thought about using it as well, but when I checked the documentation, there was no suggestion of getting it done the way @belisarius and @daniel suggested. If the documentation could be updated in that direction in future releases, it would be helpful.

Community
  • 1
  • 1
Phil
  • 815
  • 1
  • 8
  • 15
  • You should check the **More information** section in the help. There is useful info there. In the **Drop** help entry you'll find `{n} element n only` :D – Dr. belisarius Mar 14 '11 at 16:50
  • @belisarius: yes. just saw it. it feels a little lost in the maze though...thanks. – Phil Mar 14 '11 at 20:12
  • That feeling is normal. It takes time to learn to navigate the help system and the inventory of functions is _huge_ – Dr. belisarius Mar 14 '11 at 20:27

2 Answers2

9

Part directly supports lists of indices when slicing arrays. The following definitions exploit that:

takeOperator[a_?MatrixQ, rows_List, cols_List] :=
  a[[rows, cols]]

dropOperator[a_?MatrixQ, rows_List, cols_List] :=
 a[[##]]& @@ complementaryIndices[a, rows, cols]

complementaryIndices[a_?MatrixQ, rows_List, cols_List] :=
  Complement @@@ Transpose @ {Range /@ Dimensions @ a, {rows, cols}}

Example use:

a = RandomInteger[1000, {5000, 5000}];
First @ Timing @ takeOperator[a, Range[1, 5000, 2], Range[1, 5000, 2]]
(* 0.016 *)

First @ Timing @ dropOperator[a, Range[1, 5000, 2], Range[1, 5000, 2]]
(* 0.015 *)
Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
WReach
  • 18,098
  • 3
  • 49
  • 93
3

You can also use explicit ranges in a way that is fairly efficient. They may provide some more flexibility. Here is your example.

a = RandomInteger[1000, {5000, 5000}];

Timing[b = Drop[a, {101}, {101}];]

Out[66]= {0.041993, Null}

Timing[
  c = a[[Join[Range[100], Range[102, 5000]], 
   Join[Range[100], Range[102, 5000]]]];]

Out[67]= {0.061991, Null}

c == b

Out[62]= True

I would also suggest use of Span except offhand I do not see how to get it to work in this setting.

Daniel Lichtblau Wolfram Research

Daniel Lichtblau
  • 6,854
  • 1
  • 23
  • 30
  • @WReach: Thanks. To the point. I think it would be helpful if WRI could seamlessly integrate some choice support provided her in its software documentation illustrating the use of various functions of mathematica. – Phil Mar 14 '11 at 16:54