5
$\begingroup$

Delete is not suitable to delete the rows of a matrix, as illustrated below:

  SeedRandom[0];
; r = 100
; rows = RandomReal[{0, 1}, {r, 2}]
; toDrop = Select[Range[r], PrimeQ]
; reducedRows = Delete[rows, toDrop]

Mathematica graphics

I know that I can always do something like

  toKeep = Complement[Range[r], toDrop]
; reducedRows = rows[[toKeep]]

...but this strikes me as inefficient, at least whenever toKeep is large (IOW, whenever r is much greater than Length[toDrop]).

Is there any other built-in that achieves what Delete[rows, toDrop] aspires to?

$\endgroup$
  • 1
    $\begingroup$ toDrop = Transpose[{Select[Range[r], PrimeQ]}] $\endgroup$ – ciao May 20 '16 at 19:04
  • 6
    $\begingroup$ Have you tried Delete[rows, List /@ toDrop]? $\endgroup$ – J. M.'s discontentment May 20 '16 at 19:10
  • $\begingroup$ Despite acknowledgement of Complement I feel that this problem is already described in other questions: (17002), (20228), (43785), (108336). Note that the answers below largely duplicate methods already given in answer to these. I shall probably mark this as a duplicate unless someone makes a compelling argument against that. $\endgroup$ – Mr.Wizard May 20 '16 at 20:26
  • $\begingroup$ Also related (StackOverflow): Efficient way to pick/delete a list of rows/columns in a matrix in Mathematica $\endgroup$ – user1066 May 21 '16 at 14:29
  • $\begingroup$ @J.M.: Would you kindly post your comment as an answer? $\endgroup$ – kjo May 21 '16 at 17:19
7
$\begingroup$

Make the to-be-dropped rows vanish:

rows[[toDrop]] = ##&[]

or as a function:

f = Module[{m = #, d = #2}, m[[d]] = ##&[]; m] &;

f[rows, toDrop]

Some timings

ClearAll[f0, f1, f2, f3, f4, f5]
f0 = ReplacePart[#, Transpose[{#2}] -> Nothing[]]&; (* ciao's answer *)
f1 = ReplacePart[#, Thread[#2 -> Sequence[]]] &; (* v9 version of ciao's answer*)
f2 = Module[{m = #, d = #2}, m[[d]] = ## &[]; m] &;
f3 = #[[Complement[Range@Length@#, #2]]] &; (* from george2079's deleted answer*)
f4 = Delete[#, Transpose[{#2}]] &; (* from ciao's comment *)
f5 = Delete[#, List /@ #2] &; (* from J.M.'s comment *)


SeedRandom[0];
r = 1000000;
rows = RandomReal[{0, 1}, {r, 2}];
toDrop = Select[Range[r], PrimeQ];
{HoldForm[#], First[AbsoluteTiming[#[rows, toDrop]]]} & /@ {f0, f1, f2, f3, f4, f5} // Grid

Mathematica graphics

Equal @@ (#[rows, toDrop] & /@ {f0, f1, f2, f3, f4, f5})

True

| improve this answer | |
$\endgroup$
10
$\begingroup$

Probably the simplest way will be:

reducedRows = ReplacePart[rows, Transpose[{toDrop}] -> Nothing[]]
| improve this answer | |
$\endgroup$
  • $\begingroup$ I believe you need to do List /@ toDrop -> Nothing[]. (Cant verify with 10.1 though) $\endgroup$ – george2079 May 20 '16 at 20:01
  • 1
    $\begingroup$ @george2079 - oops, copied wrong - fixed (Transpose faster than map List) $\endgroup$ – ciao May 20 '16 at 20:05
  • 3
    $\begingroup$ (+1) because I've learned Nothing. $\endgroup$ – Jens May 20 '16 at 21:25
  • $\begingroup$ I didn't know Nothing as well, I was using ##&[] instead. I'll do a find and replace in all my code ! $\endgroup$ – faysou May 21 '16 at 13:45
  • 2
    $\begingroup$ I fixed the Transpose correction. Also you don't need Nothing[], Nothing only works. $\endgroup$ – faysou May 21 '16 at 13:54
2
$\begingroup$

A solution that keeps instead of drops.

toKeep = Select[Range[r], PrimeQ /* Not];
reducedRows = rows[[toKeep]];

Hope this helps.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.