【发布时间】:2021-11-01 19:04:04
【问题描述】:
我正在尝试将非 IOB 标记转换为 conllu 文件中的 IOB。
文件的两个示例行是:
2 Ute Ute PROPN NE Case=Nom|Gender=Fem|Number=Sing 1 appos _ NE=PER_23|Morph=nsf
3 Wedemeier Wedemeier PROPN NE Case=Nom|Gender=Fem|Number=Sing 2 flat _ SpaceAfter=No|NE=PER_23|Morph=nsf
我想拥有
2 Ute Ute PROPN NE Case=Nom|Gender=Fem|Number=Sing 1 appos _ NE=B-PER|Morph=nsf
3 Wedemeier Wedemeier PROPN NE Case=Nom|Gender=Fem|Number=Sing 2 flat _ SpaceAfter=No|NE=I-PER|Morph=nsf
我现在想解析文件,将所有出现的“NE=NamedEntityTag_Number”更改为 IOB(类型并不重要,只需将每个“NE=field_type_number(在示例中为“NE=PER_23”)更改为(NE= B-PER 和 NE=I-PER)。PER 可以是 list_of_fields 中的任何字段。因此,我创建了一个包含所有命名实体标签的 list_of_fields。由于 conllu 文件保存为文本文件,因此我正在解析文本由于不是所有的行都包含命名实体标签,所以我首先检查,是否有命名实体标签在该行中,如果是,我检查下一行是否有相同的标签(包括相同的数字),以及该行这很重要:当下一行包含具有相同编号 id 的相同注释时,它属于同一实体,因此,第一行必须是 B-PER,而该行的后续必须是 I- PER。
我正在尝试使用fileinput,只是为了改变NE的部分。
希望有人能帮忙,谢谢!
`
import fileinput
import re
list_of_fields = ["PER", "ORG", "LOC", "GPE", "OTH"]
with fileinput.FileInput(file, inplace=True, backup=".bak") as file:
for line in file:
ne = [annotation for annotation in list_of_fields if (annotation in line)]
if re.compile(r"^NE="+ne+"\_\d+$") in line:
if re.compile(r"^NE="+ne+"\_\d+$") in next(line) == re.compile(r"^NE="+ne+"\_\d+$") in line:
re.sub(r"^NE="+ne+"\_\d+$", r"NE=B-"+ne, line)
re.sub(r"^NE="+ne+"\_\d+$", r"NE=I-"+ne, next(line))
else:
re.sub(r"^NE=" + ne + "\_\d+$", r"NE=B-" + ne, line)`
【问题讨论】:
-
我对这种文件格式一无所知,但你不能在循环文件时使用
next(),因为这会耗尽迭代器。此外,如果您可以提供一些输入和预期输出来证明您描述的问题,这将有所帮助。 -
我调整了上面的描述。我只需要适当地切换所有“NE=...”
-
每行是否只有您列出的一个字段?字段的值(例如 PER_23)是否总是出现在整个文件中按顺序更改的组中?
-
是的,每一行要么一个 NE= 要么没有!不,数字不会按顺序变化。因此,两条线(FC Bayern München)可能是 ORG_74、ORG_74 和 ORG_74(因为它们构建一个单元,因此编号相同,因此表示为 ORG(组织))。但是,ORG 的下一次出现可能是 ORG_215,而不是 ORG_75。在新的注释样式中,第一个 ORG_74 (FC) 将是 B-ORG、Bayern I-ORG 和 München I-ORG。
标签: python-3.x regex text-parsing named-entity-recognition