Skip to content

Components

A set of components for spaCy pipelines. Each one is a class with two methods: __init__, which registers an extension of Doc at initialization, and __call__, which takes a Doc object and returns it with the statistics attached. With them a text is annotated and measured in one pass, and the statistics travel with the document.

Note

Writing components of your own is described in the corresponding section of the documentation of spaCy. The examples below use the model es_core_news_sm, which is installed apart: python -m spacy download es_core_news_sm (see installation).

Names

The factories carry the prefix of the library - ests_basic, ests_readability, ests_diversity, ests_morph, ests_syntax, ests_cohesion - because the registry of spaCy is one for the whole process: a plain basic would collide with the component of any other library registering that name, and spaCy answers a second registration with ValueError [E004].

They are declared as entry points of spacy_factories, so a pipeline saved with these components - nlp.to_disk(path), spacy package, a training config - loads with spacy.load(path) in a process that never imports the library.

The name of the pipe is free and is what the extension is called, so the short form is one argument away:

nlp.add_pipe("ests_basic", name="basic", last=True)
doc = nlp("El gato duerme")
doc._.basic.n_words

Without name the pipe and the extension keep the name of the factory (doc._.ests_basic). The same component can be added twice under different names, which is how two presets or two sets of parameters live in one pipeline.

Serialization

A component keeps an object of statistics in doc._.<name>, and spaCy cannot serialize it: Doc.to_bytes(), DocBin(store_user_data=True) and nlp.pipe(..., n_process>1) fail with these components in the pipeline. To save a document, leave the user data out (doc.to_bytes(exclude=["user_data"])) or keep doc._.<name>.get_stats() on your own; for multiprocessing compute the statistics in the main process after nlp.pipe, without the components.

What each component needs

Component Factory Statistics Needs
BasicStatsComponent ests_basic BasicStats nothing
ReadabilityStatsComponent ests_readability ReadabilityStats nothing
DiversityStatsComponent ests_diversity DiversityStats nothing
MorphStatsComponent ests_morph MorphStats parts of speech and lemmas
SyntaxStatsComponent ests_syntax SyntaxStats a parse and lemmas
CohesionStatsComponent ests_cohesion CohesionStats parts of speech and lemmas

A document with no words - an empty string, whitespace, punctuation alone - passes through every component untouched, its extension left at None, so that one such document in a corpus does not stop nlp.pipe. A missing annotation is another matter: that is an error of the pipeline and it is raised.

In the pipeline of es_core_news_sm the parts of speech come from the morphologizer (a tagger alone gives the tag of the corpus and not the part of speech of Universal Dependencies; with an attribute_ruler it does give it), the parse from the parser and the lemmas from the lemmatizer. A component whose annotation is missing raises SourceError when the document goes through it, excluded components included: without the lemmatizer every lemma is an empty string, which would make every noun of a text overlap with every other.

BasicStatsComponent

ests.components.BasicStatsComponent

The component of the basic statistics of a text.

Parameters:

Parameter Type Default Description
nlp Language - Language object
name str "ests_basic" Name of the component in the pipeline

Example

Code:

# Import the libraries
import ests
import spacy

# Load the model of spaCy
nlp = spacy.load("es_core_news_sm")

# Add the component
nlp.add_pipe("ests_basic", name="basic", last=True)

# Read the computed statistics
doc = nlp("El gato duerme en la ventana. Los niños juegan en el parque.")
doc._.basic.n_words, doc._.basic.c_letters

Result:

(12, {2: 5, 3: 1, 4: 1, 5: 1, 6: 3, 7: 1})

ReadabilityStatsComponent

ests.components.ReadabilityStatsComponent

The component of the readability metrics of a text.

Parameters:

Parameter Type Default Description
nlp Language - Language object
name str "ests_readability" Name of the component in the pipeline
preset str "general" Preset of the coefficients (general, classic)
basic str None Name of the extension of a component of basic statistics, whose object is used instead of computing them again

An unknown preset raises ParameterError when the component is added, not when a document goes through it.

The readability metrics are computed on the basic statistics, so a pipeline holding both components computes them twice unless basic names the extension of the first one - nlp.add_pipe("ests_readability", config={"basic": "basic"}) after a component named basic. On the Spanish pages of this site that takes a document from 0.025 s to 0.015 s, and the saving grows with every further preset. A name that holds no basic statistics, or a component that runs after this one, raises SourceError.

Example

Code:

...

# Add the component with the classic coefficients
nlp.add_pipe(
    "ests_readability",
    name="readability_classic",
    config={"preset": "classic"},
    last=True,
)

# Read the computed metrics
doc = nlp("El gato duerme en la ventana. Los niños juegan en el parque.")
round(doc._.readability_classic.flesch_reading_easy, 2)

Result:

105.72

DiversityStatsComponent

ests.components.DiversityStatsComponent

The component of the lexical diversity metrics of a text.

Parameters:

Parameter Type Default Description
nlp Language - Language object
name str "ests_diversity" Name of the component in the pipeline
window_len int 50 Window size for MATTR and segment size for MSTTR
mtld_threshold float 0.72 TTR threshold for MTLD, MA-MTLD and MTLD-W
mtld_min_len int 10 Minimum factor length for MTLD, MA-MTLD and MTLD-W
hdd_sample_size int 42 Sample size for HD-D
log_base float 10 Logarithm base for the Summer, Maas and Dugast metrics

A parameter out of its range raises ParameterError when the component is added.

Example

Code:

...

# Add the component with a natural logarithm and a window of 100 words
nlp.add_pipe(
    "ests_diversity",
    name="diversity_ln",
    config={"window_len": 100, "log_base": 2.718281828459045},
    last=True,
)

# Read the computed metrics
doc = nlp("El gato duerme en la ventana. Los niños juegan en el parque.")
round(doc._.diversity_ln.ttr, 3)

Result:

0.833

MorphStatsComponent

ests.components.MorphStatsComponent

The component of the morphological statistics of a text. The parts of speech and the features are read from the annotation of the model, so the pipeline needs a morphologizer (or a tagger with an attribute_ruler) and a lemmatizer before the component.

Parameters:

Parameter Type Default Description
nlp Language - Language object
name str "ests_morph" Name of the component in the pipeline

Example

Code:

...

# Add the component
nlp.add_pipe("ests_morph", name="morph", last=True)

# Read the computed statistics
doc = nlp("El gato duerme en la ventana. Los niños juegan en el parque.")
doc._.morph.pos[:4]

Result:

('DET', 'NOUN', 'VERB', 'ADP')

SyntaxStatsComponent

ests.components.SyntaxStatsComponent

The component of the syntactic statistics of a text. The statistics are computed on the dependency tree, so the pipeline needs a parser and a lemmatizer before the component.

Parameters:

Parameter Type Default Description
nlp Language - Language object
name str "ests_syntax" Name of the component in the pipeline

Example

Code:

...

# Add the component
nlp.add_pipe("ests_syntax", name="syntax", last=True)

# Read the computed statistics
doc = nlp("El gato duerme en la ventana. Los niños juegan en el parque.")
doc._.syntax.tree_depth, doc._.syntax.mean_dependency_distance

Result:

(2.0, 1.6)

CohesionStatsComponent

ests.components.CohesionStatsComponent

The component of the cohesion statistics of a text. The features are read from the annotation of the model, so the pipeline needs a morphologizer (or a tagger with an attribute_ruler) and a lemmatizer before the component.

Parameters:

Parameter Type Default Description
nlp Language - Language object
name str "ests_cohesion" Name of the component in the pipeline

Example

Code:

...

# Add the component
nlp.add_pipe("ests_cohesion", name="cohesion", last=True)

# Read the computed statistics
doc = nlp("El informe fue aprobado. Sin embargo, el informe no resuelve el problema.")
doc._.cohesion.noun_overlap_adjacent, round(doc._.cohesion.connectors, 2)

Result:

(1.0, 83.33)

Everything in one pipeline

The six components can live side by side, and then one pass over a document gives every statistic of the library that a Doc can carry.

Example

Code:

import ests
import spacy

nlp = spacy.load("es_core_news_sm")
for factory in ("basic", "readability", "diversity", "morph", "syntax", "cohesion"):
    nlp.add_pipe(f"ests_{factory}", name=factory, last=True)

doc = nlp("El gato duerme en la ventana. Los niños juegan en el parque.")
(
    doc._.basic.n_words,
    round(doc._.readability.flesch_reading_easy, 2),
    round(doc._.diversity.ttr, 3),
    doc._.morph.pos[:2],
    doc._.syntax.tree_depth,
    doc._.cohesion.p_given,
)

Result:

(12, 102.19, 0.833, ('DET', 'NOUN'), 2.0, 0.0)