3

I am selecting data from series on basis of threshold .

>>> s = pd.Series(np.random.randn(5))
>>> s
0   -0.308855
1   -0.031073
2    0.872700
3   -0.547615
4    0.633501
dtype: float64
>>> cfg = {'threshold' : 0 , 'op' : 'less' }
>>> ops = {'less' : '<', 'more': '>' , 'equal': '==' , 'not equal' : '!='}
>>> ops[cfg['op']]
'<'
>>> s[s < cfg['threshold']]
0   -0.308855
1   -0.031073
3   -0.547615
dtype: float64

I want to use ops[cfg['op']] in last line of code , instead of '<'. I am willing to change key , values of ops dict if required (like -lt instead of <). How this can be done?

cs95
  • 379,657
  • 97
  • 704
  • 746
Bharat Sharma
  • 1,081
  • 3
  • 11
  • 23
  • 2
    use `operator.xx` - `gt`, `lt`, `eq`, `ne` – cs95 Sep 26 '17 at 08:36
  • 2
    See [How to pass an operator to a python function](https://stackoverflow.com/questions/18591778/how-to-pass-an-operator-to-a-python-function) – Zero Sep 26 '17 at 08:39

2 Answers2

4

I'm all about @cᴏʟᴅsᴘᴇᴇᴅ's answer and @Zero's linked Q&A...
But here is an alternative with numexpr

import numexpr as ne

s[ne.evaluate('s {} {}'.format(ops[cfg['op']], cfg['threshold']))]

0   -0.308855
1   -0.031073
3   -0.547615
Name: A, dtype: float64

I reopened this question after having been closed as a dup of How to pass an operator to a python function?

The question and answers are great and I showed my appreciation with up votes.

Asking in the context of a pandas.Series opens it up to using answers that include numpy and numexpr. Whereas trying to answer the dup target with this answer would be pure nonsense.

piRSquared
  • 285,575
  • 57
  • 475
  • 624
2

Define a dictionary of methods that can stand in for your operators.

import operator    
d = {
         'more'  : operator.gt,
         'less'  : operator.lt,
         'equal' : operator.eq, 
         'not equal' : operator.ne
   }

Now, just index into your dictionary and apply your function parameters.

m = d[cfg['op']](s, cfg['threshold'])
m

0    False
1     True
2     True
3    False
4    False
dtype: bool

s[m]

1   -0.262054
2   -1.300810
dtype: float64

Here,

d[cfg['op']](s, cfg['threshold']) 

Is translated into

operator.lt(s, 0)
cs95
  • 379,657
  • 97
  • 704
  • 746
  • You may have the accepted answer... But I had it first for about a second (-: and back again. Apparently OP likes both answer and can't decide. – piRSquared Sep 26 '17 at 08:53
  • 1
    @piRSquared it wasn’t long ago when I was thanking you for the support that led to my silver badge, and now it’s time for me to do the same for my gold badge. Couldn’t have done it without the help and support, and upvotes. So, thank you. :) – cs95 Sep 26 '17 at 23:31
  • I didn't do it... you did! Congrats! And likewise. – piRSquared Sep 26 '17 at 23:33