python pandas.Series.str.contains WHOLE WORD
<p>df (Pandas Dataframe) has three rows.</p>

<pre><code>col_name
"This is Donald."
"His hands are so small"
"Why are his fingers so short?"
</code></pre>

<p>I'd like to extract the row that contains "is" and "small".</p>

<p>If I do</p>

<pre><code>df.col_name.str.contains("is|small", case=False)
</code></pre>

<p>Then it catches "His" as well- which I don't want.</p>

<p>Is below query is the right way to catch the whole word in df.series?</p>

<pre><code>df.col_name.str.contains("\bis\b|\bsmall\b", case=False)
</code></pre>

<p>First, you may want to convert everything to lowercase, remove punctuation and whitespace and then convert the result into a set of words.</p>

<pre><code>import string

df['words'] = [set(words) for words in
    df['col_name']
    .str.lower()
    .str.replace('[{0}]*'.format(string.punctuation), '')
    .str.strip()
    .str.split()
]

&gt;&gt;&gt; df
                        col_name                                words
0                This is Donald.                   {this, is, donald}
1         His hands are so small         {small, his, so, are, hands}
2  Why are his fingers so short?  {short, fingers, his, so, are, why}
</code></pre>

<p>You can now use boolean indexing to see if all of your target words are in these new word sets.</p>

<pre><code>target_words = ['is', 'small']
# Convert target words to lower case just to be safe.
target_words = [word.lower() for word in target_words]

df['match'] = df.words.apply(lambda words: all(target_word in words 
                                               for target_word in target_words))


print(df)
# Output: 
#                         col_name                                words  match
# 0                This is Donald.                   {this, is, donald}  False
# 1         His hands are so small         {small, his, so, are, hands}  False
# 2  Why are his fingers so short?  {short, fingers, his, so, are, why}  False    

target_words = ['so', 'small']
target_words = [word.lower() for word in target_words]

df['match'] = df.words.apply(lambda words: all(target_word in words 
                                               for target_word in target_words))

print(df)
# Output:
# Output: 
#                         col_name                                words  match
# 0                This is Donald.                   {this, is, donald}  False
# 1         His hands are so small         {small, his, so, are, hands}   True
# 2  Why are his fingers so short?  {short, fingers, his, so, are, why}  False    
</code></pre>

<p>To extract the matching rows:</p>

<pre><code>&gt;&gt;&gt; df.loc[df.match, 'col_name']
# Output:
# 1    His hands are so small
# Name: col_name, dtype: object
</code></pre>

<p>To make this all into a single statement using boolean indexing:</p>

<pre><code>df.loc[[all(target_word in word_set for target_word in target_words) 
        for word_set in (set(words) for words in
                         df['col_name']
                         .str.lower()
                         .str.replace('[{0}]*'.format(string.punctuation), '')
                         .str.strip()
                         .str.split())], :]
</code></pre>

python regex pandas dataframe