107

Looks ugly:

df_cut = df_new[
             (
             (df_new['l_ext']==31) |
             (df_new['l_ext']==22) |
             (df_new['l_ext']==30) |
             (df_new['l_ext']==25) |
             (df_new['l_ext']==64)
             )
            ]

Does not work:

df_cut = df_new[(df_new['l_ext'] in [31, 22, 30, 25, 64])]

Is there an elegant and working solution of the above "problem"?

Roman
  • 124,451
  • 167
  • 349
  • 456

2 Answers2

241

Use isin

df_new[df_new['l_ext'].isin([31, 22, 30, 25, 64])]
waitingkuo
  • 89,478
  • 28
  • 112
  • 118
  • 27
    This is one of those less-intuitive `pandas` syntax features... You don't know unless you know. – openwonk Sep 07 '16 at 23:45
  • 4
    What's the negative of isin? I'm looking for a way to filter out the list elements. – Augmented Jacob Sep 21 '16 at 18:38
  • 1
    numpy.logical_not(foo.isin(x)) and another method suggested by Pandas author: http://stackoverflow.com/questions/14057007/remove-rows-not-isinx – Luke Barker Sep 28 '16 at 08:07
  • 9
    Negation using ~ should be enough for doing not isin. df_new[~df_new['l_ext'].isin([31, 22, 30, 25, 64])] – Arun Das Mar 27 '18 at 21:57
  • 1
    Be cautious, if the type of the column is ambiguous for example "object" which could be either numeric or string "isin" will automatically infer data type. – Semooze Oct 18 '21 at 14:40
15

You can use pd.DataFrame.query:

select_values = [31, 22, 30, 25, 64]
df_cut = df_new.query('l_ext in @select_values')

In the background, this uses the top-level pd.eval function.

jpp
  • 159,742
  • 34
  • 281
  • 339
  • 1
    Another alternative without having to create an extra variable: `df_new.query('l_ext.isin([31, 22, 30, 25, 64]).values')` – rachwa May 08 '22 at 20:07