Wrap your keyword with the word boundary character \b:
df['Text'].str.replace(r'\beng\b', 'engine')
0 engine is here
1 engine needs washing
2 engine is overheating
Name: Text, dtype: object
If you have multiple keywords to replace in this manner, pass a dictionary to replace with the regex=True switch:
repl = {'eng' : 'engine'}
repl = {rf'\b{k}\b': v for k, v in repl.items()}
df['Text'].replace(repl, regex=True)
0 engine is here
1 engine needs washing
2 engine is overheating
Name: Text, dtype: object
Answer from cs95 on Stack OverflowWrap your keyword with the word boundary character \b:
df['Text'].str.replace(r'\beng\b', 'engine')
0 engine is here
1 engine needs washing
2 engine is overheating
Name: Text, dtype: object
If you have multiple keywords to replace in this manner, pass a dictionary to replace with the regex=True switch:
repl = {'eng' : 'engine'}
repl = {rf'\b{k}\b': v for k, v in repl.items()}
df['Text'].replace(repl, regex=True)
0 engine is here
1 engine needs washing
2 engine is overheating
Name: Text, dtype: object
Adding a blank and fixed that problem from your own code
df['Text'].str.replace('eng ', 'engine ')
Out[736]:
0 engine is here
1 engine needs washing
2 engine is overheating
Name: Text, dtype: object
Update
df.Text.str.split(' ',expand=True).replace('eng','engine').fillna('').apply(' '.join,1)
Out[752]:
0 engine is here
1 engine needs washing
2 engine is overheating
dtype: object
Using re, in case you want to specify the series string:
df.apply(lambda x: re.sub('\s*{}$'.format(x['series']), '', x['id']), axis=1)
In case the the series string is always a predictable pattern (i.e. [a-z]) you can also try:
df['id'].apply(lambda x: re.sub('\s*[a-z]+$', '', x))
Either way the output is what you are looking for:
0 abarth 1.4
1 abarth 1
2 land rover 1.3
3 land rover 2
4 land rover 5
5 mazda 4.55
You could use str.rpartition to split the ids on the last space.
In [169]: parts = df['id'].str.rpartition(' ')[[0,2]]; parts
Out[169]:
0 2
0 abarth 1.4 a
1 abarth 1 a
2 land rover 1.3 r
3 land rover 2
4 land rover 5 g
5 mazda 4.55 bl
Then you could use == to compare parts[2] to df['series']:
In [170]: mask = (parts[2] == df['series']); mask
Out[170]:
0 True
1 True
2 True
3 False
4 True
5 True
dtype: bool
And finally, use df['id'].where to replace df['id] with parts[0] where mask is True:
import pandas as pd
df = pd.DataFrame(
{'id' : ['abarth 1.4 a','abarth 1 a','land rover 1.3 r','land rover 2',
'land rover 5 g','mazda 4.55 bl'],
'series': ['a','a','r','','g', 'bl'] })
parts = df['id'].str.rpartition(' ')[[0,2]]
mask = (parts[2] == df['series'])
df['id'] = df['id'].where(~mask, parts[0], axis=0)
print(df)
yields
id series
0 abarth 1.4 a
1 abarth 1 a
2 land rover 1.3 r
3 land rover 2
4 land rover 5 g
5 mazda 4.55 bl
Alternatively, you could use
import re
def remove_series(x):
pat = r'{}$'.format(x['series'])
return re.sub(pat, '', x['id'])
df['id'] = df.apply(remove_series, axis=1)
But calling df.apply with a custom function tends to be much slower than using built-in vectorize methods such as those used in the first method.
Use replace
In [126]: df.replace(['very bad', 'bad', 'poor', 'good', 'very good'],
[1, 2, 3, 4, 5])
Out[126]:
resp A B C
0 1 3 3 4
1 2 4 3 4
2 3 5 5 5
3 4 2 3 2
4 5 1 1 1
5 6 3 4 1
6 7 4 4 4
7 8 5 5 5
8 9 2 2 1
9 10 1 1 1
Considering data is your pandas DataFrame you can also use:
data.replace({'very bad': 1, 'bad': 2, 'poor': 3, 'good': 4, 'very good': 5}, inplace=True)