Message Boards Message Boards

0
|
5906 Views
|
16 Replies
|
11 Total Likes
View groups...
Share
Share this post:

Test for the position of the first non-numeric value?

Posted 8 years ago

Hello

I have the feeling that my question is pretty basic, but the answer will help me to understand a bit more on the Wolfram Language. Here it is:

Consider the following list:

{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}

How can I find the position of the first element of the list that is not numeric? I have tried to use Position with pattern _?NumericQ[#] & (just to see if it finds 1) but it didn't work. This shows that I don't know how this type of expressions works

The solution does not need to use Position. I've just used for the sake of understanding expressions. Different solutions are welcome.

Thank you for your time and patience.

Ed

POSTED BY: Eduardo Mendes
16 Replies
Posted 8 years ago

Thank you all ever so much.

POSTED BY: Eduardo Mendes
Posted 8 years ago

Many thanks. LengthWhile is definitely a good alternative.

POSTED BY: Eduardo Mendes

It is the worst choice!

In[1]:= tList = RandomChoice[{"a", "b", "c"}, 1000000];
tList[[777777]] = 1;

In[3]:= Position[NumericQ /@ tList, True][[1]] // AbsoluteTiming
Position[tList, _?NumericQ, 1] // AbsoluteTiming
Position[tList, _?(NumericQ[#] &), 1] // AbsoluteTiming
FirstPosition[tList, _?NumericQ, 1] // AbsoluteTiming
FirstCase[tList, _?NumericQ] // AbsoluteTiming
SelectFirst[tList, NumericQ] // AbsoluteTiming
(LengthWhile[tList, Not@*NumericQ] + 1) // AbsoluteTiming

Out[3]= {0.369993, {777777}}

Out[4]= {0.39994, {{777777}}}

Out[5]= {0.820059, {{777777}}}

Out[6]= {0.32599, {777777}}

Out[7]= {0.302233, 1}

Out[8]= {0.211421, 1}

Out[9]= {2.50185, 777777}

In[10]:= BarChart@{
   Position[NumericQ /@ tList, True][[1]] // AbsoluteTiming,
   Position[tList, _?NumericQ, 1] // AbsoluteTiming,
   Position[tList, _?(NumericQ[#] &), 1] // AbsoluteTiming,
   FirstPosition[tList, _?NumericQ, 1] // AbsoluteTiming,
   FirstCase[tList, _?NumericQ] // AbsoluteTiming,
   SelectFirst[tList, NumericQ] // AbsoluteTiming,
   (LengthWhile[tList, Not@*NumericQ] + 1) // AbsoluteTiming
   }[[All, 1]]

enter image description here

Very surprising that LengthWhile is so slow, perhaps because it is not compiled? while any pattern-matching is (either directly or JIT). If you know that is in 'ordinary' number then you can speed it up even more. Function-testing is much slower than checking the Head of an expression. Also NumberQ instead of NumericQ can be a bit faster. It all depends on what you consider a number... (btw you could also add |_Complex if you like...

tList=RandomChoice[{a,b,c},1000000];
tList[[777777]]=1;

Position[NumericQ/@tList,True][[1]]//AbsoluteTiming
Position[tList,_?NumericQ,1]//AbsoluteTiming
Position[tList,_?(NumericQ[#]&),1]//AbsoluteTiming
FirstPosition[tList,_?NumericQ,1]//AbsoluteTiming
FirstCase[tList,_?NumericQ]//AbsoluteTiming
SelectFirst[tList,NumericQ]//AbsoluteTiming
(LengthWhile[tList,Not@*NumericQ]+1)//AbsoluteTiming

BarChart@{Position[NumericQ/@tList,True][[1]]//AbsoluteTiming,Position[tList,_?NumericQ,1]//AbsoluteTiming,Position[tList,_?(NumericQ[#]&),1]//AbsoluteTiming,FirstPosition[tList,_?NumericQ,1]//AbsoluteTiming,FirstCase[tList,_?NumericQ]//AbsoluteTiming,
SelectFirst[tList,NumericQ]//AbsoluteTiming,
SelectFirst[tList,NumberQ]//AbsoluteTiming,(LengthWhile[tList,Not@*NumericQ]+1)//AbsoluteTiming,
FirstPosition[tList,_Real|_Integer,1]//AbsoluteTiming,
FirstCase[tList,_Real|_Integer]//AbsoluteTiming
}[[All,1]]

enter image description here

POSTED BY: Sander Huisman

It seems very strange such a big time difference for the function LengthWhile.

Especially compared to SelectFirst, as these are (nearly) the same functions... One keeps a counter, the other gives the item, should be nearly same timings.... My results are from an upcoming version, so if it is a 'bug' it is not yet fixed in the next release. I will send this info to Wolfram...

POSTED BY: Sander Huisman

It is very interesting to know what is the cause of this situation...

I just send it to them, if I hear some details I will share it here (if possible as this info might be subject to an NDA)...

POSTED BY: Sander Huisman

Perfect!

When you only want the first, it is better to perhaps use:

FirstPosition
FirstCase
LengthWhile[....,Not@*NumericQ]+1

Such that; when it finds the first 'hit' it will not continue the scan of the (possibly very long) list

POSTED BY: Sander Huisman

I just found out there is also SelectFirst, if you don't want the index but rather the element itself...

POSTED BY: Sander Huisman
Posted 8 years ago

Dear Bill

Thank you ever so much. I will definitely explore your examples further

Regards

Ed

POSTED BY: Eduardo Mendes
Posted 8 years ago

Perhaps start simply and avoid the use of shortcut notation when you aren't sure how things work

In[1]:= Map[NumericQ, {0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}]

Out[1]= {True, False, False}

and thus you would probably want to get the position of the first False.

There is a new function FirstPosition mentioned at the bottom of the help page on Position

In[2]:= FirstPosition[Map[NumericQ, {0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}], False]

Out[2]= {2}

Now can we perhaps understand why your _?NumericQ[#] & didn't work? The & turned all that into a function and Position is looking for a pattern as the third argument, not a function.

We can use a pattern with a condition that only matches numeric items, this way

In[3]:= Position[{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}, z_ /; NumericQ[z]]

Out[3]= {{1}, {2, 1}, {2, 2, 1, 2}, {2, 2, 2, 2}, {3, 1, 1}, {3, 1, 2, 2}, {3, 2, 1}, {3, 2, 2, 2}, {3, 3, 1, 2}, {3, 3, 2, 2}}

which does successfully find the position of numeric items, but matches those at every level and that doesn't look like what you were looking for. You could augment that with a level argument like this

In[3]:= Position[{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}, z_ /; NumericQ[z], 1]

Out[3]= {{1}}

which shows that only the first item in the list is numeric.

Perhaps you can use some of these ideas to explore further

POSTED BY: Bill Simpson
Posted 8 years ago

Many thanks.

Would you mind tell me why _?NumericQ[#] & won't work?

Position[{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + 
   x^5 y^2}, _?NumericQ[#]  &]
POSTED BY: Eduardo Mendes

Absolutely well explained by Bill. Only for the simplicity it may be observed additionally that

In[1]:= Position[{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}, _?NumericQ, 1]

Out[1]= {{1}}

In[2]:= Position[{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}, _?(NumericQ[#] &), 1]

Out[2]= {{1}}

In[3]:= FirstPosition[{0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}, _?NumericQ, 1]

Out[3]= {1}
In[1]:= Position[NumericQ /@ {0, -1 + x^2 y^2, -x^3 + 2 x^2 y + x^5 y^2}, True][[1]]

Out[1]= {1}
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract