Can we to refer to a dictionary get a value from the key while replacing in Python?

Viewed 62

I have a flat file with terms and sentences. If any term is found in the sentence, I need to append its id to the term (term|id). Pattern match should be case insensitive. Also, we need to retain the same case as in the sentence. Is it possible to refer to dictionary to get the value using it's key in a replace call?

from pandas import DataFrame
import re

df = {'id':[11,12,13,14,15,16],
    'term': ['Ford', 'EXpensive', 'TOYOTA', 'Mercedes Benz', 'electric', 'cars'],
        'sentence': ['F-FORD FORD/FORD is less expensive than Mercedes Benz.' ,'toyota, hyundai mileage is good compared to ford','tesla is an electric-car','toyota too has electric cars','CARS','CArs are expensive.']
        }
#Dataframe creation
df = DataFrame(df,columns= ['id','term','sentence'])

#Dictionary creation
dict = {}
l_term = list(df['term'])
l_id = list(df['id'])

for i,j in zip(l_term,l_id):
    dict[str(i)] = j

#Building patterns to replace
pattern = r'(?i)(?<!-)(?<!\w)(?:{})(?!\w)'.format('|'.join(map(re.escape, sorted(df["term"],key=len,reverse=True))))

#Replace
df["sentence"].replace(pattern, r"\g<0>|present",, inplace=True,regex=True)

Instead of |present I need to refer to dictionary like |dict.get(\g<0>) or is there any other approach to achieve this? Also, if we found cars twice for 16,17. We can append either one.

The expected outcome is

F-FORD FORD|11/FORD|11 is less expensive|12 than Mercedes Benz|14.
toyota|13, hyundai mileage is good compared to ford|11
tesla is an electric|15-car
toyota|13 too has electric|15 cars|16
CARS|16
CArs|16 are expensive|12.

1 Answers

You may use a slight modification of the current code:

from pandas import DataFrame
import re

df = {'id':[11,12,13,14,15,16],
    'term': ['Ford', 'EXpensive', 'TOYOTA', 'Mercedes Benz', 'electric', 'cars'],
        'sentence': ['F-FORD FORD/FORD is less expensive than Mercedes Benz.' ,'toyota, hyundai mileage is good compared to ford','tesla is an electric-car','toyota too has electric cars','CARS','CArs are expensive.']
        }
#Dataframe creation
df = DataFrame(df,columns= ['id','term','sentence'])

#Dictionary creation
dct = {}
l_term = list(df['term'])
l_id = list(df['id'])

for i,j in zip(l_term,l_id):
    dct[str(i).upper()] = j

#Building patterns to replace
pattern = r'(?i)(?<!-)(?<!\w)(?:{})(?!\w)'.format('|'.join(map(re.escape, sorted(df["term"],key=len,reverse=True))))

#Replace
df["sentence"]=df["sentence"].str.replace(pattern, lambda x: "{}|{}".format(x.group(),dct[x.group().upper()]))

NOTES:

  • dict is a reserved name, do not name variables dict, use dct
  • dct[str(i).upper()] = j - the uppercased key is added to the dictionary to enable case insensitive search by key in the dictionary
  • df["sentence"]=df["sentence"].str.replace(pattern, lambda x: "{}|{}".format(x.group(),dct[x.group().upper()])) is the main (last) line, it uses Series.str.replace that allows using a callable as the replacement argument and once the pattern matches, the match is passed to the lambda expression as x Match object where the value is retrieved with dct[x.group().upper()] and the whole match is accessed with x.group().
Related