Here is a short example that should do the trick with regular expressions:
import re
rep = {"condition1": "", "condition2": "text"} # define desired replacements here
# use these three lines to do the replacement
rep = dict((re.escape(k), v) for k, v in rep.items())
pattern = re.compile("|".join(rep.keys()))
text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)
For example:
>>> pattern.sub(lambda m: rep[re.escape(m.group(0))], "(condition1) and --condition2--")
'() and --text--'
Answer from Andrew Clark on Stack OverflowHere is a short example that should do the trick with regular expressions:
import re
rep = {"condition1": "", "condition2": "text"} # define desired replacements here
# use these three lines to do the replacement
rep = dict((re.escape(k), v) for k, v in rep.items())
pattern = re.compile("|".join(rep.keys()))
text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)
For example:
>>> pattern.sub(lambda m: rep[re.escape(m.group(0))], "(condition1) and --condition2--")
'() and --text--'
You could just make a nice little looping function.
def replace_all(text, dic):
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
where text is the complete string and dic is a dictionary — each definition is a string that will replace a match to the term.
Note: in Python 3, iteritems() has been replaced with items()
Careful: Python dictionaries don't have a reliable order for iteration. This solution only solves your problem if:
- order of replacements is irrelevant
- it's ok for a replacement to change the results of previous replacements
Update: The above statement related to ordering of insertion does not apply to Python versions greater than or equal to 3.6, as standard dicts were changed to use insertion ordering for iteration.
For instance:
d = { "cat": "dog", "dog": "pig"}
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, d)
print(my_sentence)
Possible output #1:
"This is my pig and this is my pig."
Possible output #2
"This is my dog and this is my pig."
One possible fix is to use an OrderedDict.
from collections import OrderedDict
def replace_all(text, dic):
for i, j in dic.items():
text = text.replace(i, j)
return text
od = OrderedDict([("cat", "dog"), ("dog", "pig")])
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, od)
print(my_sentence)
Output:
"This is my pig and this is my pig."
Careful #2: Inefficient if your text string is too big or there are many pairs in the dictionary.
Which is the better way to include multiple '.replace()' ?
Feature Proposal: Multi-String Replacement Using a Dictionary in the .replace() Method - Ideas - Discussions on Python.org
Vectorized .str.replace() for multiple characters in pandas
python - Replace multiple substrings in a Pandas series with a value - Stack Overflow
I have a string formatted timestamp that I would like to replace some characters.
Which is the better way to do this (of the two I have thought of!) ?
1 -
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", t_obj).replace("-", "").replace(" ", "_").replace(":", "")2 -
timestamp = time.strftime("%Y-%m-%d %H:%M:%S", t_obj)
timestamp = timestamp .replace("-", "")
timestamp = timestamp .replace(" ", "_")
timestamp = timestamp .replace(":", "")First approach reads nicer but wouldn't readability wouldn't scale as well if I wanted to do more replaces.
Second one, is using the same variable name over and over like that until it's in the state you want considered bad practice maybe?
Cheers !
I have a dataframe:
{'country': {0: 'Afghanistan?*', 1: 'Albania?*'},
'region': {0: 'Asia', 1: 'Europe'},
'subregion': {0: 'Southern Asia', 1: 'Southern Europe'},
'rate_per_1000': {0: 6.7, 1: 2.1},
'count': {0: '2,474', 1: '61'},
'year': {0: 2018, 1: 2020},
'source': {0: 'NSO', 1: 'NSO'}}
country region subregion rate_per_1000 count year source
0 Afghanistan?* Asia Southern Asia 6.7 2,474 2018 NSO
1 Albania?* Europe Southern Europe 2.1 61 2020 NSOThere are multiple bad characters here that I want to get rid of. I made a short function for .apply() to get rid of them, however I am looping over a defined list of bad characters. This gives a bad code smell to me, I think this operation could be more vectorized in some way. This is what I've tried:
bad_chars = ['?', '*', ',']
def string_cleaner(col):
if col.dtype == 'object':
for char in bad_chars:
col = col.str.replace(f'{char}', '')
return col
homicide_by_country = homicide_by_country.apply(string_cleaner)
homicide_by_country
country region subregion rate_per_1000 count year source
0 Afghanistan Asia Southern Asia None 2474 None NSO
1 Albania Europe Southern Europe None 61 None NSOMy desired outcome is a more pythonic/pandonic technique for accomplishing the same outcome.
You may notice for some reason my rate_per_1000 columns goes blank. I haven't troubleshot that problem yet but if you spot something obvious I'm all ears.
You can perform this task by forming a |-separated string. This works because pd.Series.str.replace accepts regex:
Replace occurrences of pattern/regex in the Series/Index with some other string. Equivalent to str.replace() or re.sub().
This avoids the need to create a dictionary.
import pandas as pd
df = pd.DataFrame({'A': ['LOCAL TEST', 'TEST FOREIGN', 'ANOTHER HELLO', 'NOTHING']})
pattern = '|'.join(['LOCAL', 'FOREIGN', 'HELLO'])
df['A'] = df['A'].str.replace(pattern, 'CORP', regex=True)
# A
# 0 CORP TEST
# 1 TEST CORP
# 2 ANOTHER CORP
# 3 NOTHING
The answer of @Rakesh is very neat but does not allow for substrings. With a small change however, it does.
- Use a replacement dictionary because it makes it much more generic
- Add the keyword argument
regex=TruetoSeries.replace()(notSeries.str.replace) This does two things actually: It changes your replacement to regex replacement, which is much more powerful but you will have to escape special characters. Beware for that. Secondly it will make the replace work on substrings instead of the entire string. Which is really cool!
replacement = {
"LOCAL": "CORP",
"FOREIGN": "CORP",
"HELLO": "CORP"
}
dataUS['sec_type'].replace(replacement, regex=True)
Full code example
dataUS = pd.DataFrame({'sec_type': ['LOCAL', 'Sample text LOCAL', 'Sample text LOCAL sample FOREIGN']})
replacement = {
"LOCAL": "CORP",
"FOREIGN": "CORP",
"HELLO": "CORP"
}
dataUS['sec_type'].replace(replacement, regex=True)
Output
0 CORP
1 CORP
2 Sample text CORP
3 Sample text CORP sample CORP
Name: sec_type, dtype: object
so i used .replace() to remove a certain character from a filename
but now i want to do it for more characters.
how is this done in python?
this is what i tried:
char_remove = ['?', '"', '!']
for char in char_remove:
movie_title = (str(submission.title) + '.mp4').replace(char_remove, '')but i got
TypeError: replace() argument 1 must be str, not list
Try like this :
import pandas as pd
df = pd.DataFrame({'ID':[1,2,3,4], 'Description':['he wants some epples', 'she bought 2kgs of bakana', 'he got nothing', 'she took potato and tomat']})
replacement = {
"epples": "apples",
"bakana": "banana",
"tomat": "tomato"
}
print(df['Description'].replace(replacement, regex=True))
Output :
0 he wants some apples
1 she bought 2kgs of banana
2 he got nothing
3 she took potato and tomato
yes, in str.replace(something, toReplaceWith), you missed toReplaceWith so that it errors