Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have an application where I need to drop some arbitrary list of columns from a ragged array (where of course the shortest array rows have at least all the specified columns).

E.g., given a ragged list:

{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6, 7, 8, 9}, 
 {1, 2, 3, 4, 5, 6, 7, 8}}

and a column selection of {1, 3, 5}, the resulting array after dropping these is

{2, 4, 6, 7, 8, 9, 10}, {2, 4}, {2, 4, 6, 7, 8, 9}, {2, 4, 6, 7, 8}

The closest I could find searching here was How to use “Drop” function to drop matrix' rows and columns in an arbitrary way?, but that has (nice) solutions for well-formed arrays, while I'm working with ragged arrays of (1000-100000) X (20-2000).

I've tried schemes using unique padding to the length of the longest row, operating, then dropping the padding and found that slow.

I'm currently using:

colDropper[array_, cols_] := Module[{s = Split[Sort@cols, #2 == #1 + 1 &]},
  Fold[Drop[#, {}, #2] &, array, (DeleteDuplicates /@ s[[All, {1, -1}]]) - 
     Most@Accumulate@Prepend[Length /@ s, 0]]]

which does the job and performs... OK, but there's got to be a way that combines elegance and speed (unfortunately, as with most data I work with, not machine-precision is the usual here so compiling seems out...)

share|improve this question

1 Answer 1

up vote 9 down vote accepted

Here is a simple method that seems to be somewhat faster than yours on unpackable data:

colDrop[array_, drop_] :=
  Module[{m = array}, m[[All, drop]] = Sequence[]; m]

Test:

data = Range /@ RandomInteger[{15, 50}, 500000];
data = Map[FromCharacterCode, data + 37, {2}];

colDropper[data, {1, 3, 5, 8, 10, 11}] // Timing // First
colDrop[data, {1, 3, 5, 8, 10, 11}]    // Timing // First
1.217

0.733

Also worth consideration is a rather direct application of Delete:

colDrop2[array_, drop_] :=
  Outer[Delete, array, {List /@ drop}, 1]

colDrop2[data, {1, 3, 5, 8, 10, 11}] // Timing // First
0.952
share|improve this answer
    
Pretty cool. It didn't come to my mind that the 2D All spec would work, but in hindsight this is logical. +1. –  Leonid Shifrin Mar 11 at 13:07
    
Ok, this is clearly the winner. Deleting mine, since this one uses the same idea, but does it right. –  Leonid Shifrin Mar 11 at 13:10
    
@Leonid Thanks for the correction. I have hope that you will find another method worthy of posting; you rarely fail. :-) –  Mr.Wizard Mar 11 at 13:13
    
I doubt there is a simpler one in this case. –  Leonid Shifrin Mar 11 at 13:18
    
I should've made a test for unpacable data :( +1 :) –  Kuba Mar 11 at 13:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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