United Statesjenojp/negspacy
spaCy pipeline object for negating concepts in text
![]()
negspacy: negation for spaCy
spaCy pipeline object for negating concepts in text. Based on the NegEx algorithm.
NegEx - A Simple Algorithm for Identifying Negated Findings and Diseases in Discharge Summaries Chapman, Bridewell, Hanbury, Cooper, Buchanan https://doi.org/10.1006/jbin.2001.1029
What's new
Version 1.0 is a major version update providing support for spaCy 3.0's new interface for adding pipeline components. As a result, it is not backwards compatible with previous versions of negspacy.
If your project uses spaCy 2.3.5 or earlier, you will need to use version 0.1.9. See archived readme.
Installation and usage
Install the library.
pip install negspacy
Import library and spaCy.
import spacy
from negspacy.negation import Negex
Load spacy language model. Add negspacy pipeline object. Filtering on entity types is optional.
nlp = spacy.load("en_core_web_sm")
nlp.add_pipe("negex", config={"ent_types":["PERSON","ORG"]})
View negations.
doc = nlp("She does not like Steve Jobs but likes Apple products.")
for e in doc.ents:
print(e.text, e._.negex)
Steve Jobs True
Apple False
Consider pairing with scispacy to find UMLS concepts in text and process negations.
NegEx Patterns
- pseudo_negations - phrases that are false triggers, ambiguous negations, or double negatives
- preceding_negations - negation phrases that precede an entity
- following_negations - negation phrases that follow an entity
- termination - phrases that cut a sentence in parts, for purposes of negation detection (.e.g., "but")
Termsets
Designate termset to use, en_clinical is used by default.
en= phrases for general english language texten_clinicalDEFAULT = adds phrases specific to clinical domain to general englishen_clinical_sensitive= adds additional phrases to help rule out historical and possibly irrelevant entities
To set:
from negspacy.negation import Negex
from negspacy.termsets import termset
ts = termset("en")
nlp = spacy.load("en_core_web_sm")
nlp.add_pipe(
"negex",
config={
"neg_termset":ts.get_patterns()
}
)
Additional Functionality
Change patterns or view patterns in use
Replace all patterns with your own set
nlp = spacy.load("en_core_web_sm")
nlp.add_pipe(
"negex",
config={
"neg_termset":{
"pseudo_negations": ["might not"],
"preceding_negations": ["not"],
"following_negations":["declined"],
"termination": ["but","however"]
}
}
)
Add and remove individual patterns on the fly from built-in termsets
from negspacy.termsets import termset
ts = termset("en")
ts.add_patterns({
"pseudo_negations": ["my favorite pattern"],
"termination": ["these are", "great patterns", "but"],
"preceding_negations": ["wow a negation"],
"following_negations": ["extra negation"],
})
#OR
ts.remove_patterns(
{
"termination": ["these are", "great patterns"],
"pseudo_negations": ["my favorite pattern"],
"preceding_negations": ["denied", "wow a negation"],
"following_negations": ["unlikely", "extra negation"],
}
)
View patterns in use
from negspacy.termsets import termset
ts = termset("en_clinical")
print(ts.get_patterns())
Negations with Spans
Span Groups can be negated by providing a list of span keys to the span_keys argument.
Load spacy language model that adds spans to the Doc object.
nlp = spacy.load("your_span_cat_model")
# 'sc' is the default SpanGroup spans_key
nlp.add_pipe("negex", config={"span_keys":["sc"]})
View negations.
doc = nlp("Analysis showed no sign of Human TR Beta 1 mRNA")
for span in doc.spans["sc"]:
print(span.text, span.label, span._.negex)
Human TR Beta 1 PROTEIN True
Human TR Beta 1 mRNA RNA True
Negations in noun chunks
Depending on the Named Entity Recognition model you are using, you may have negations "chunked together" with nouns. For example:
nlp = spacy.load("en_core_sci_sm")
doc = nlp("There is no headache.")
for e in doc.ents:
print(e.text)
# no headache
This would cause the Negex algorithm to miss the preceding negation. To account for this, you can add a chunk_prefix:
nlp = spacy.load("en_core_sci_sm")
ts = termset("en_clinical")
nlp.add_pipe(
"negex",
config={
"chunk_prefix": ["no"],
},
last=True,
)
doc = nlp("There is no headache.")
for e in doc.ents:
print(e.text, e._.negex)
# no headache True
Contributing
Authors
- Jeno Pizarro
License
Other libraries
This library is featured in the spaCy Universe. Check it out for other useful libraries and inspiration.
If you're looking for a spaCy pipeline object to extract values that correspond to a named entity (e.g., birth dates, account numbers, or laboratory results) take a look at extractacy.
![]()
Similar Projects
Discover other similar projects and AI models.
🛸 Use pretrained transformers like BERT, XLNet and GPT-2 in spaCy
🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.
Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.
:octocat: 分享 GitHub 上有趣、入门级的开源项目。Share interesting, entry-level open source projects on GitHub.
Build Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.