Python 空间替换令牌

Python 空间替换令牌,python,spacy,Python,Spacy,我试图在不破坏句子空间结构的情况下替换一个单词。假设我有一句话text=“嗨,这是我的狗。”。我想用辛巴来代替狗。按照我的回答: 导入空间 nlp=空间负荷(“核心网络负荷”) 从spacy.tokens导入文档 doc1=nlp(“嗨,这是我的狗。”) new_words=[token.text if token.text!=“dog”else“Simba”表示doc1中的令牌] 文档(doc1.vocab,单词=新词) #嗨,这是我的辛巴。 注意,在句号前的结尾处有一个额外的空格(应该是嗨

我试图在不破坏句子空间结构的情况下替换一个单词。假设我有一句话
text=“嗨,这是我的狗。”
。我想用辛巴来代替狗。按照我的回答:

导入空间
nlp=空间负荷(“核心网络负荷”)
从spacy.tokens导入文档
doc1=nlp(“嗨,这是我的狗。”)
new_words=[token.text if token.text!=“dog”else“Simba”表示doc1中的令牌]
文档(doc1.vocab,单词=新词)
#嗨,这是我的辛巴。

注意,在句号前的结尾处有一个额外的空格(应该是
嗨,这是我的辛巴。
)。有没有办法消除这种行为。对于一般的python字符串处理回答,我也很高兴。

以可扩展的方式实现这一点的一种方法是使用spacy Matcher并修改Doc对象,如下所示:

from spacy.matcher import Matcher

matcher = Matcher(nlp.vocab)
matcher.add("dog", on_match, [{"LOWER": "dog"}])

def replace_word(doc, replacement):
    doc = nlp(doc)
    match_id, start, end = matcher(doc)[0] #assuming only one match replacement

    return nlp.make_doc(doc[:start].text + f" {replacement}" + doc[-1].text)

>>> replace_word("Hi this is my dog.", "Simba")
Hi this is my Simba.
当然,您可以扩展此模式并通过在函数中添加for循环来替换“dog”的所有实例,而不仅仅是替换第一个匹配项,您还可以交换匹配器中的规则以更改不同的单词

这样做的好处是,尽管它更复杂,但它允许您将其他信息保存在spacy Doc对象中,如引理、词类、实体、依赖项解析等

但是如果你有一根绳子,你就不必担心这些。要使用普通Python实现这一点,我将使用正则表达式

import re
def replace_word_re(text, word, replacement):
    return re.sub(word, replacement, text)

>>> replace_word_re("Hi this is my dog.", "dog", "Simba")
Hi this is my Simba.

看来你在找一个常规的替代品?我会的

string = "Hi this is my dog."
string = string.replace("dog","Simba")

text='你好,这是我的狗'
打印(text.replace('dog','simba'))

多亏@lora johns我找到了答案。因此,不必走matcher路线,我认为这可能是一个更简单的答案:

new_words=[(token.idx,len(“dog”))表示doc1中的token if token.text.lower()==“dog”]
#替换字从头到尾的顺序相反
新词=已排序(新词,关键字=λx:-x[0])
对于i,l,用新词:
text=文本[:i]+“辛巴”+文本[i+l:]

以下函数替换任意数量的匹配项(使用spaCy查找),保持与原始文本相同的空格,并适当处理边缘情况(如匹配项位于文本开头时):

导入空间
从spacy.matcher导入matcher
nlp=空间负荷(“核心网络负荷”)
matcher=matcher(nlp.vocab)
add(“dog”,None,[{“LOWER”:“dog”}])
def替换字(原始文本,替换):
tok=nlp(原始文本)
文本=“”
缓冲区\u开始=0
对于匹配器(tok)中的匹配开始:
如果match_start>buffer_start:#如果我们跳过了一些标记,那么让我们将它们添加进来(如果可用,则使用尾随空格)
text+=tok[buffer\u start:match\u start]。text+tok[match\u start-1]。空白_
text+=replacement+tok[match_start]。空格#Replace token,如果可用,则使用尾随空格
缓冲区开始=匹配开始+1
text+=tok[buffer_start:]text
返回文本
>>>替换单词(“嗨,这是我的狗。”,“辛巴”)
嗨,这是我的辛巴。
>>>替换单词(“嗨,这条狗是我的狗。”,“辛巴”)
嗨,这个辛巴是我的辛巴。

下面是我如何使用regex的:

sentence = 'Hi this is my dog. dogdog this is mydog'
replacement = 'Simba'
to_replace = 'dog'
st = re.sub(f'(\W|^)+({to_replace})(\W|$)+', f'\g<1>{replacement}\g<3>', sentence)
这是我的狗。狗狗这是我的狗的 替换=‘辛巴’ to_replace='dog' st=re.sub(f'(\W |^)+({to|u replace})(\W |$)+',f'\g{replacement}\g',句子)
您可以指定要添加空格的位置:

import spacy
nlp = spacy.load("en_core_web_lg")
from spacy.tokens import Doc

doc1 = nlp("Hi this is my dog.")
new_words = [token.text if token.text!="dog" else "Simba" for token in doc1]
spaces = [True]*len(doc1)
spaces[-2:] = [False, False]
Doc(doc1.vocab, words=new_words, spaces=spaces)

当“保留空间结构”时,更换后的预期结果是什么?更新为
嗨,这是我的辛巴。
。谢谢。此代码不运行,
doc1
从未定义。请修改你的代码。(仅仅进行字符串替换的问题是,您会丢失spacy Doc对象中的所有信息。好吧,我不知道什么是
spacy
,所以我就把它留在这里。spacy是一个NLP库,它将文档作为字符串接收,并将其转换为一个大的c结构,存储有关文档和所有子对象的信息其中的结构,如依赖项解析、词类、引理、频率、索引等。保持所有信息的完整性非常有用,将其简化为字符串处理会消除底层结构。:)啊哈,听起来很棒:)很好!您也可以直接访问
token.lower
。它运行平稳,除非匹配在文本末尾,否则它返回错误…以修复错误替换
text+=tok[buffer\u start::]。text
if buffer\u start
这方面的问题是单词和子字符串之间没有区别,即“doggy”变成了“Simbagy”。对,这就是使用基于令牌的解决方案而不仅仅是正则表达式的原因。您也可以将正则表达式设置为完全匹配。