我有两个pandas数据帧。一个包含文本,另一个包含我想在文本中搜索和替换的术语。我有一个方法来做到这一点,但我想添加条件。条件是,如果该术语包含单词“不”和“#”;或者没有'没有'之前最多三个字,不要替换。
在下面的示例中,ID 2根据上述条件被错误地替换。
示例文字:
d = {'ID': [1, 2, 3], 'Text': ['here is some random text', 'no such random text, none here', 'more random text']}
text_df = pd.DataFrame(data=d)
示例条款:
d = {'Replace_item': ['<RANDOM_REPLACED>', '<HERE_REPLACED>', '<SOME_REPLACED>'], 'Text': ['random', 'here', 'some']}
replace_terms_df = pd.DataFrame(data=d)
替换术语的方法(ID 2根据条件不正确):
text_df['Text'] = [z.replace(x, y) for (x, y, z) in zip(replace_terms_df.Text, replace_terms_df.Replace_item, text_df.Text)]
目标数据帧(考虑条件):
d = {'ID': [1, 2, 3], 'Text': ['<HERE_REPLACED> is <SOME_REPLACED> <RANDOM_REPLACED> text', 'no such random text, none here', 'more <RANDOM_REPLACED> text']}
target_df = pd.DataFrame(data=d)
请询问您是否需要清晰。谢谢。
答案 0 :(得分:1)
首先创建替换项目的字典会有所帮助。您可以执行以下操作:
# create a dict
make_dict = replace_terms_df.set_index('Text')['Replace_item'].to_dict()
# this function does the replacement work
def g_val(strin, dic):
d = []
if 'none' in strin or 'no' in strin:
return strin
else:
for i in strin.split():
if i not in dic:
d.append(i)
else:
d.append(dic[i])
return ' '.join(d)
## apply the function
text_df['new_text'] = text_df['Text'].apply(lambda x: g_val(x, dic=make_dict))
## check output
print(text_df['new_text'])
0 <HERE_REPLACED> is <SOME_REPLACED> <RANDOM_REP...
1 no such random text, none here
2 more <RANDOM_REPLACED> text
<强>解释强>
在功能中,我们正在做:
1.如果字符串包含none或no,我们按原样返回字符串
2.如果它不包含none或no,我们检查单词是否在字典中可用,如果是,我们返回替换值,否则返回现有值。
答案 1 :(得分:1)
使用正则表达式解决方案检查以下代码:
import re
# set up the regex pattern
# the words which should be skipped, must be whole word and case-insensitive
ptn_to_skip = re.compile(r'\b(?:no|none)\b', re.IGNORECASE)
# the pattern for mapping
# Note: any regex meta charaters need to be escaped, or it will fail.
ptn_to_map = re.compile(r'\b(' + '|'.join(replace_terms_df.Text.tolist()) + r')\b')
# map from text to Replace_item
terms_map = replace_terms_df.set_index('Text').Replace_item
def adjust_text(x):
# if 1 - 3 ptn_to_skip found, return x,
# otherwise, map the matched group \1 with terms_map
if 0 < len(ptn_to_skip.findall(x)) <= 3:
return x
else:
return ptn_to_map.sub(lambda y: terms_map[y.group(1)], x)
# do the conversion:
text_df['new_text'] = text_df.Text.apply(adjust_text)
一些注释:
replace_terms_df.Text
中的文本转换为正则表达式。默认情况下,文本都是纯文本,没有正则表达式元字符。 <强>更新强>
首先添加一个新逻辑来检查被排除的单词['no','none'],如果匹配,则找到下一个0-3单词,这些单词本身不被排除 - 单词,将它们保存到\ 1,实际匹配的搜索词将保存在\ 2中。然后在正则表达式替换部分中,以不同方式处理它们。
以下是新代码:
import re
# pattern to excluded words (must match whole-word and case insensitive)
ptn_to_excluded = r'\b(?i:no|none)\b'
# ptn_1 to match the excluded-words ['no', 'none'] and the following maximal 3 words which are not excluded-words
# print(ptn_1) --> \b(?i:no|none)\b\s*(?:(?!\b(?i:no|none)\b)\S+\s*){,3}
# where (?:(?!\b(?i:no|none)\b)\S+\s*) matches any words '\S+' which is not in ['no', 'none'] followed by optional white-spaces
# {,3} to specify matches up to 3 words
ptn_1 = r'{0}\s*(?:(?!{0})\S+\s*){{,3}}'.format(ptn_to_excluded)
# ptn_2 is the list of words you want to convert with your terms_map
# print(ptn_2) --> \b(?:random|here|some)\b
ptn_2 = r'\b(?:' + '|'.join(replace_terms_df.Text.tolist()) + r')\b'
# new pattern based on the alternation using ptn_1 and ptn_2
# regex: (ptn_1)|(ptn_2)
new_ptn = re.compile('({})|({})'.format(ptn_1, ptn_2))
# map from text to Replace_item
terms_map = replace_terms_df.set_index('Text').Replace_item
# regex function to do the convertion
def adjust_map(x):
return new_ptn.sub(lambda m: m.group(1) or terms_map[m.group(2)], x)
# do the conversion:
text_df['new_text'] = text_df.Text.apply(adjust_map)
<强>解释强>
我定义了两个子模式:
工作原理:
以下一些测试:
In []: print(new_ptn)
re.compile('(\\b(?i:no|none)\\b\\s*(?:(?!\\b(?i:no|none)\\b)\\S+\\s*){,3})|(\\b(random|here|some)\\b)')
In[]: for i in [
'yes, no such a random text'
, 'yes, no such a a random text'
, 'no no no such a random text no such here here here no'
]: print('{}:\n [{}]'.format(i, adjust_map(i)))
...:
yes, no such a random text:
[yes, no such a random text]
yes, no such a a random text:
[yes, no such a a <RANDOM_REPLACED> text]
no no no such a random text no such here here here no:
[no no no such a random text no such here here <HERE_REPLACED> no]
让我知道这是否有效。
需要考虑的事项:
ptn_to_excluded
就足够了。