Sam Perry
Sam Perry

Reputation: 2614

Python Pandas: String Contains and Doesn't Contain

I'm trying to match rows of a Pandas DataFrame that contains and doesn't contain certain strings. For example:

import pandas
df = pandas.Series(['ab1', 'ab2', 'b2', 'c3'])
df[df.str.contains("b")]

Output:

0    ab1
1    ab2
2     b2
dtype: object

Desired output:

2     b2
dtype: object

Question: is there an elegant way of saying something like this?

df[[df.str.contains("b")==True] and [df.str.contains("a")==False]]
# Doesn't give desired outcome

Upvotes: 12

Views: 29274

Answers (3)

lstodd
lstodd

Reputation: 168

You can use .loc and ~ to index:

df.loc[(df.str.contains("b")) & (~df.str.contains("a"))]

2    b2
dtype: object

Upvotes: 2

maxymoo
maxymoo

Reputation: 36555

You're almost there, you just haven't got the syntax quite right, it should be:

df[(df.str.contains("b") == True) & (df.str.contains("a") == False)]

Another approach which might be cleaner if you have a lot of conditions to apply would to be to chain your filters together with reduce or a loop:

from functools import reduce
filters = [("a", False), ("b", True)]
reduce(lambda df, f: df[df.str.contains(f[0]) == f[1]], filters, df)
#outputs b2

Upvotes: 14

behzad.nouri
behzad.nouri

Reputation: 78021

Either:

>>> ts.str.contains('b') & ~ts.str.contains('a')
0    False
1    False
2     True
3    False
dtype: bool

or use regex:

>>> ts.str.contains('^[^a]*b[^a]*$')
0    False
1    False
2     True
3    False
dtype: bool

Upvotes: 9

Related Questions