8
$\begingroup$

I would like to know is it possible to find positions of False in t:

t = Table[RandomChoice[{True, False}], 6000];
Flatten[Position[t, False]] // AbsoluteTiming

faster than the above method. I will appreciate any help.

$\endgroup$

3 Answers 3

9
$\begingroup$

Speed here is hindered by the fact that True/False is not a packable type in Mathematica, although I personally think it should be.

If it is possible to reformulate your problem to use 1/0 instead, which can be packed, the methods already provided (Pick and SparseArray) each become much faster.

You can convert your data using With faster than using Boole, but the overhead is still significant:

SeedRandom[1]
t = Table[RandomChoice[{True, False}], 6000];

b = Developer`ToPackedArray @ 
      With[{True = 1, False = 0}, Evaluate @ t]; // RepeatedTiming
{0.000151, Null}

Now observe how fast Pick becomes compared to its direct application on t:

r1 = Pick[Range @ Length @ t, t, False]; // RepeatedTiming

r2 = Pick[Range @ Length @ b, b, 0]; // RepeatedTiming

r1 === r2
{0.000343, Null}

{0.0000509, Null}

True

Combined with the overhead of the conversion this is a little slower than kglr's method (0.000176 second on my machine), but it gives an idea of the performance that is possible if you can avoid True/False and use packed integers instead.

$\endgroup$
6
  • 3
    $\begingroup$ Wow, I am really surprised that With[{True = 1, False = 0}, Evaluate @ t] is faster than Boole. $\endgroup$ Commented Aug 10, 2018 at 6:54
  • 2
    $\begingroup$ @Henrik It's kind of disappointing isn't it? $\endgroup$
    – Mr.Wizard
    Commented Aug 10, 2018 at 14:58
  • $\begingroup$ Yes, it is... As well as the general slowness of Booleans in Mathematica. $\endgroup$ Commented Aug 10, 2018 at 20:06
  • 2
    $\begingroup$ @Henrik Yet another case where there is room for improvement in the core language that is neglected, all the while new functions applicable only for some are added. $\endgroup$
    – Mr.Wizard
    Commented Aug 10, 2018 at 20:20
  • $\begingroup$ sigh I am totally with you in that respect. $\endgroup$ Commented Aug 10, 2018 at 20:21
6
$\begingroup$

You can use Pick:

t = Table[RandomChoice[{True,False}],6000];
r1 = Flatten[Position[t,False]]; //RepeatedTiming
r2 = Pick[Range@Length@t,t,False]; //RepeatedTiming

r1 === r2

{0.0023, Null}

{0.00036, Null}

True

Another useful alternative is PositionIndex, especially when you want to know the positions of different values:

r3 = PositionIndex[t]; //RepeatedTiming

r1 === r2 === r3[False]

{0.00070, Null}

True

$\endgroup$
6
$\begingroup$

Using SparseArray with "AdjacencyLists" or with "NonzeroPositions" is faster than alternatives posted so far:

SeedRandom[1]
t = Table[RandomChoice[{True, False}], 6000];

r4 =SparseArray[t, Automatic, True]["AdjacencyLists"]; //RepeatedTiming  // First

0.00021

r5 = Flatten@SparseArray[t, Automatic, True]["NonzeroPositions"]; //RepeatedTiming// First

0.00021

versus

r1 = Flatten[Position[t, False]]; // RepeatedTiming // First 

0.0027

r2 = Pick[Range @ Length @ t, t, False]; // RepeatedTiming // First 

0.000414

r3 = PositionIndex[t][False]; // RepeatedTiming // First 

0.000830

(b = Developer`ToPackedArray @ With[{True =1, False =0}, Evaluate @ t]; 
 r6 = Pick[Range @ Length @ b, b, 0];) //RepeatedTiming  // First  

0.00028

SameQ[r1, r2, r3, r4, r5, r6]

True

where r1 is from OP, r2 and r3 are from Carl Woll's and r6 is from Mr.Wizard's answer.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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