Cohesion statistics¶
CohesionStats(source, sents_extractor=None, connectors=None)
The cohesion statistics of a text in the manner of Coh-Metrix: the overlap of the sentences, the givenness, the temporal cohesion and the connectors of a dictionary. The sentences are compared by lemmas. The data source is a Doc object of spaCy with the parts of speech and the lemmas, split into sentences by its boundaries, or by the sentence extractor over its text when one is given or the Doc has none.
Raises:
SourceTypeError- an extractor of another type, a source that is not aDoc, connectors that are not a dictionary of phrases and pairs of strings;SourceError- a source without parts of speech, lemmas or words;ParameterError- an unknown class or kind of a connector.
import spacy
from spacy.tokens import Doc
from anyts.cohesion_stats import CohesionStats
class English(CohesionStats):
@classmethod
def load_connectors(cls):
return {"however": ("adversative", "secondary")}
# The cat slept. However, the cat woke.
doc = Doc(
spacy.blank("en").vocab,
words=["The", "cat", "slept", ".", "However", ",", "the", "cat", "woke", "."],
spaces=[True, True, False, True, False, True, True, True, False, False],
pos=["DET", "NOUN", "VERB", "PUNCT", "ADV", "PUNCT", "DET", "NOUN", "VERB", "PUNCT"],
lemmas=["the", "cat", "sleep", ".", "however", ",", "the", "cat", "wake", "."],
morphs=["", "", "Aspect=Perf|Tense=Past", "", "", "", "", "", "Aspect=Perf|Tense=Past", ""],
sent_starts=[True, False, False, False, True, False, False, False, False, False],
)
stats = English(doc)
stats.print_stats()
Statistic | Value
---------------------------------------------------------------------------
Noun overlap in adjacent sentences | 1.00
Noun overlap in all pairs of sentences | 1.00
Argument overlap in adjacent sentences | 1.00
Argument overlap in all pairs of sentences | 1.00
Content word overlap in adjacent sentences | 1.00
Content word overlap in all pairs of sentences | 1.00
Share of shared content words in adjacent sentences | 0.40
Share of shared content words in all pairs of sentences | 0.40
Share of pronouns | 0.00
Ratio of pronouns to nouns | 0.00
Share of demonstratives | 0.00
Share of content words seen before | 0.20
Repetition of the tense in adjacent sentences | 1.00
Repetition of the aspect in adjacent sentences | 1.00
Temporal cohesion | 1.00
Connectors per 1000 words | 142.86
Connectors linking a sentence to the ones before per 1000 words | 142.86
Connectors linking the parts of a sentence per 1000 words | 0.00
Causal connectors per 1000 words | 0.00
Adversative connectors per 1000 words | 142.86
Concessive connectors per 1000 words | 0.00
Temporal connectors per 1000 words | 0.00
Additive connectors per 1000 words | 0.00
Conditional connectors per 1000 words | 0.00
Reformulative connectors per 1000 words | 0.00
Primary connectors per 1000 words | 0.00
Secondary connectors per 1000 words | 142.86
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
source |
Doc |
- | Data source: a Doc with the parts of speech and the lemmas, or what analyze reads |
sents_extractor |
SentsExtractor |
None |
Sentence extraction tool; given here, it splits a Doc by its text whatever its boundaries |
connectors |
dict[str, tuple[str, str]] |
None |
Class and kind by connector; those of load_connectors by default |
Attributes¶
| Attribute | Type | Description |
|---|---|---|
words, lemmas |
tuple[tuple[str]] |
Words and lemmas of every sentence with words |
n_sents, n_words |
int |
Numbers of the sentences with words and of the words |
n_nouns, n_pronouns, n_demonstratives, n_content_words |
int |
Numbers of the words by kind |
n_given |
int |
Number of the content words whose lemma was used before |
n_connectors, connector_spans, c_connectors |
int, tuple[Connector], dict[str, int] |
Number of the connectors, their occurrences and their number by connector |
n_inter_connectors |
int |
Number of the inter-sentential connectors |
stats.connector_spans
stats.c_connectors
(Connector(sent=1, start=0, end=1, text='however', cls='adversative', kind='secondary'),)
{'however': 1}
Metrics¶
Every metric is an attribute of the object, computed when it is created; get_stats gives those of stats_desc, all but mood_repetition by default. The functions of the cards take a sentence as the collection of its elements - lemmas of nouns, arguments or content words, values of a feature of its verbs - and see no language.
| Metric | Measures | Range | Higher means |
|---|---|---|---|
noun_overlap_adjacent |
Share of the adjacent pairs of sentences sharing a noun | 0-1, nan for one sentence |
Neighbouring sentences tied tighter |
noun_overlap_all |
Share of all the pairs of sentences sharing a noun | 0-1, nan for one sentence |
The whole text tied tighter |
argument_overlap_adjacent |
Share of the adjacent pairs sharing a noun or a pronoun | 0-1, nan for one sentence |
Neighbouring sentences tied tighter |
argument_overlap_all |
Share of all the pairs sharing a noun or a pronoun | 0-1, nan for one sentence |
The whole text tied tighter |
content_overlap_adjacent |
Share of the adjacent pairs sharing a content word | 0-1, nan for one sentence |
Neighbouring sentences tied tighter |
content_overlap_all |
Share of all the pairs sharing a content word | 0-1, nan for one sentence |
The whole text tied tighter |
content_overlap_prop_adjacent |
Mean share of the shared content words (Dice) in the adjacent pairs | 0-1, nan for one sentence |
More words shared by neighbours |
content_overlap_prop_all |
Mean share of the shared content words (Dice) in all the pairs | 0-1, nan for one sentence |
More words shared across the text |
p_pronouns |
Share of the pronouns among the words | 0-1 | More reference by pronouns |
pronoun_noun_ratio |
Ratio of the pronouns to the nouns | 0 and above, nan without nouns |
More pronouns per noun |
p_demonstratives |
Share of the demonstratives among the words | 0-1 | More pointing back |
p_given |
Share of the content words whose lemma was used before in the text | 0-1, nan without content words |
More given information |
tense_repetition |
Share of the adjacent pairs of sentences with the same dominant tense | 0-1, nan without two adjacent sentences with the feature |
A steadier tense |
mood_repetition |
Share of the adjacent pairs with the same dominant mood | 0-1, nan without two adjacent sentences with the feature |
A steadier mood |
aspect_repetition |
Share of the adjacent pairs with the same dominant aspect | 0-1, nan without two adjacent sentences with the feature |
A steadier aspect |
temporal_cohesion |
Mean of the repetitions of temporal_features |
0-1, nan when one of them is nan |
A steadier time frame |
connectors |
Connectors per 1000 words | 0-1000 | More explicit links |
connectors_inter |
Inter-sentential connectors per 1000 words | 0-1000 | More links to the sentences before |
connectors_intra |
Intra-sentential connectors per 1000 words | 0-1000 | More links inside the sentences |
connectors_<class>, connectors_<kind> |
Connectors of a class or a kind of the matcher per 1000 words | 0-1000 | More links of the class or the kind |
Binary overlap¶
calc_overlap(sets, adjacent=True)
The binary overlap of Coh-Metrix (CRFNO1, CRFAO1, CRFSO1 over the adjacent pairs, CRFNOa, CRFAOa, CRFSOa over all of them): the share of the pairs of sentences that share at least one element; nan for a text shorter than two sentences. All the pairs are counted as in calc_overlaps, without going through them.
| Parameter | Type | Default | Description |
|---|---|---|---|
sets |
list[set[str]] |
- | Elements of every sentence |
adjacent |
bool |
True |
Count the adjacent pairs only, otherwise all the pairs |
Proportional overlap¶
calc_proportional_overlap(sets, adjacent=True)
The proportional overlap of Coh-Metrix (CRFCWO1, CRFCWOa): the Dice coefficient of a pair of sentences (dice) averaged over the pairs; nan for a text shorter than two sentences. Over all the pairs the sum is computed as in calc_overlaps, without going through them.
| Parameter | Type | Default | Description |
|---|---|---|---|
sets |
list[set[str]] |
- | Elements of every sentence |
adjacent |
bool |
True |
Count the adjacent pairs only, otherwise all the pairs |
dice(first, second)
The Dice coefficient of two sets, 0 for two empty sets.
| Parameter | Type | Default | Description |
|---|---|---|---|
first |
frozenset[str] |
- | First set |
second |
frozenset[str] |
- | Second set |
Pronouns and demonstratives¶
The pronouns, the nouns and the demonstratives are the words analyze marks so, with the features of word_info by default.
Givenness¶
count_given(sents)
The number of given elements: an element is given when the same lemma was used earlier in any sentence, the current one included; the first occurrence is new.
| Parameter | Type | Default | Description |
|---|---|---|---|
sents |
list[list[str]] |
- | Lemmas of every sentence in the order of the text |
Temporal cohesion¶
calc_repetition(sents)
The repetition of the tense and of the aspect of Coh-Metrix (SMTEMP): the share of the adjacent pairs of sentences whose verbs have the same dominant value of the feature; a pair where one of the sentences has no verb with the feature is skipped, and without a single such pair the value is nan.
| Parameter | Type | Default | Description |
|---|---|---|---|
sents |
list[list[str]] |
- | Values of the feature of the verbs of every sentence |
dominant(values)
The dominant value: the most frequent one, the first of the equally frequent; None for an empty list.
| Parameter | Type | Default | Description |
|---|---|---|---|
values |
list[str] |
- | Values |
Connectors¶
The occurrences of the connectors found in every sentence by the matcher of connector_matcher_class, per 1000 words. An inter-sentential connector links a sentence to the ones before: it opens a sentence, unless the matcher takes it for a subordinator (is_subordinator), whose clause or phrase belongs to the same sentence; the others are intra-sentential. Every class and kind of the matcher gives a density: connectors_causal, connectors_adversative, connectors_concessive, connectors_temporal, connectors_additive, connectors_conditional, connectors_reformulative, connectors_primary and connectors_secondary by default.
A list of sentences that is a string, a Doc, an iterator, a set or a table raises SourceTypeError, and so does a sentence that is not a list of strings (check_words), such as a list of spaCy tokens. The overlaps (calc_overlap, calc_proportional_overlap, calc_overlaps) take a sentence as a set too; count_given and calc_repetition count the words in order and refuse a set.
from anyts.cohesion_stats import calc_overlap, calc_repetition, count_given
sets = [{"cat", "house"}, {"cat", "dog"}, {"bird"}]
calc_overlap(sets), calc_overlap(sets, adjacent=False)
count_given([["cat", "house"], ["cat", "dog"], ["house"]])
calc_repetition([["Pres"], ["Pres", "Past", "Pres"], ["Past"]])
(0.5, 0.3333333333333333)
2
0.5
Methods¶
The methods get_stats, to_dataframe, print_stats and describe are those of the statistics interface.
Overlaps at once¶
calc_overlaps(sets, proportional=True)
The values of calc_overlap and calc_proportional_overlap over the adjacent and over all the pairs at once, as an Overlap named tuple with the fields adjacent, all, prop_adjacent and prop_all; without proportional the last two are nan. The values over all the pairs are computed without going through every pair: the sharing pairs are counted over bit masks of the sentences, and the sum of the Dice coefficients over the histograms of the lengths of the sentences holding each element, added by math.fsum so that it does not depend on the order of the elements.
| Parameter | Type | Default | Description |
|---|---|---|---|
sets |
list[set[str]] |
- | Elements of every sentence |
proportional |
bool |
True |
Compute the proportional overlap as well |
from anyts.cohesion_stats import calc_overlaps
calc_overlaps([{"cat", "house"}, {"cat", "dog"}, {"bird"}])
Overlap(adjacent=0.5, all=0.3333333333333333, prop_adjacent=0.25, prop_all=0.16666666666666666)
Connector matcher¶
ConnectorMatcher(connectors)
The search of the connectors (discourse markers: because, however, on the other hand) of a dictionary in the sentences of a text. The dictionary gives the class of every connector - causal, adversative, concessive, temporal, additive, conditional or reformulative (CONNECTOR_CLASSES) - and its kind, primary or secondary (CONNECTOR_KINDS). A connector is matched by the normalized forms of its words, the longest one at every position, without overlaps; a period or a hyphen inside a connector may be split off by the tokenizer (e.g. as e, g). An occurrence is a Connector: the number of the sentence sent, the positions start and end of its words, the connector text as the dictionary writes it, its class cls and kind kind.
Raises:
SourceTypeError- a dictionary that is not a mapping of a phrase to a pair of strings;ParameterError- an unknown class or kind.
find(words, sent_index, pos, breaks) returns the occurrences of the connectors in a sentence in the order of its words. The words are those of one sentence without punctuation, the first one its start. With the parts of speech, a one-word connector counts only with one of pos_tags or of pos_extra for its form, never after one of not_after_pos, and with one of start_only_pos only at the start of the sentence; a word without a part of speech (None) passes. Without the parts of speech the rules that read them are skipped. The positions of the punctuation marks breaks cut a connector off its neighbours: a rule does not read a word across a mark, so in so, the end the word after the comma neither blocks nor lets the connector count, unless the connector is one of read_through_marks, and a mark between the words of a connector of split_by_marks makes it none; without them the words are read as adjacent.
| Parameter | Type | Default | Description |
|---|---|---|---|
words |
list[str] |
- | Words of the sentence |
sent_index |
int |
0 |
Number of the sentence, written into the occurrences |
pos |
list[str] |
None |
Parts of speech of the words |
breaks |
set[int] |
None |
Positions of the words a punctuation mark stands before |
Words that are not a list of strings and parts of speech that are not a list of strings and None (the tags token.pos_ of spaCy, not the numbers token.pos) and positions of the marks that are not a collection raise SourceTypeError, a number of the sentence or a position of a mark that is not an integer and parts of speech not as many as the words ParameterError.
from anyts.cohesion_stats import ConnectorMatcher
class Matcher(ConnectorMatcher):
blocked_after = {"before": frozenset({"the"})}
not_after_pos = frozenset({"DET"})
matcher = Matcher(
{
"however": ("adversative", "secondary"),
"before": ("temporal", "primary"),
"and": ("additive", "primary"),
"on the other hand": ("adversative", "secondary"),
}
)
matcher.find("On the other hand he left before the end".split())
matcher.find(["The", "before", "and", "after"], pos=["DET", "ADV", "CCONJ", "ADV"])
[Connector(sent=0, start=0, end=4, text='on the other hand', cls='adversative', kind='secondary')]
[Connector(sent=0, start=2, end=3, text='and', cls='additive', kind='primary')]
is_subordinator(connector, pos=None) checks whether an occurrence of a connector ties its clause or phrase to its own sentence: a connector of subordinators, or a one-word connector whose part of speech pos is SCONJ or ADP. The clause of a subordinating conjunction and the phrase of a preposition belong to the sentence of the connector wherever it stands, so a subordinator opening a sentence (when he came, ..., despite the rain, ...) does not link it to the ones before.
For library developers¶
Language hooks of a subclass
A language library subclasses CohesionStats. By default the words and their features are read from a Doc by Universal Dependencies, and there are no connectors:
| Hook | Kind | Description |
|---|---|---|
analyze(source) |
method | Words of the sentences of a source as CohesionWord: the word, its lemma, its part of speech, whether it is a noun, a pronoun, a demonstrative, an argument and a content word, its tense, mood and aspect, and whether a punctuation mark stands before it (break_before, which the rules of the connectors do not read through); by default those of a Doc, sentence by sentence (doc_units), with the features of word_info; a library that reads a string or a Doc without these annotations overrides it |
doc_units(doc) |
method | Words of the sentences of a Doc as lists of tokens: by its boundaries, or by the extractor over its text (split_doc_units of anyts.utils) |
word_info(unit) |
method | Features of a word of a Doc; by default a noun is NOUN or PROPN, a pronoun PRON or a possessive, demonstrative or personal determiner, a demonstrative carries PronType=Dem, an argument is NOUN, PROPN or PRON, a content word one of anyts.constants.CONTENT_UD_POS and no demonstrative, and the tense, the mood and the aspect are the features Tense, Mood and Aspect |
load_connectors() |
class method | Dictionary of the connectors of the language, class and kind by connector; empty by default |
connector_matcher() |
class method | Matcher of that dictionary, built once for a class and shared by its instances and by searches outside the statistics |
connector_matcher_class |
class attribute | Class that finds the connectors with the context rules of the language; ConnectorMatcher by default. A matcher with other classes or kinds gives other connectors_* attributes, so the subclass sets its own stats_desc too |
temporal_features |
class attribute | Features of the verbs whose repetitions make the temporal cohesion: a tuple of one or more distinct ones of tense, mood and aspect (TEMPORAL_FEATURES), checked when the class is defined; tense and aspect by default, as in Coh-Metrix |
sents_extractor_class, join_hyphens |
class attributes | Sentence extractor of a Doc without boundaries, joining of the hyphenated words of a Doc |
stats_desc, stats_headers |
class attributes | Statistics of get_stats with their descriptions (COHESION_STATS_DESC by default), headers of the columns for print_stats |
messages |
class attribute | Messages of the errors by key; MESSAGES by default |
The parameters of a library - its model of a string, its word extractor - go to the constructor of its subclass, which keeps them for its analyze. An analyze that does not give sentences of CohesionWord objects raises SourceTypeError.
Rules of a connector matcher
The rules of a language are class attributes of a subclass, empty by default apart from pos_tags:
| Hook | Kind | Description |
|---|---|---|
normalize(text) |
method | Normalized form of a word and of a connector; the lower case by default |
blocked_after, blocked_before |
class attributes | Words after or before a connector, by its text, that make it no connector (before the end) |
blocked_after_pos |
class attribute | Parts of speech of the word after a connector, by its text, that make it no connector |
not_at_start |
class attribute | Connectors that do not count at the start of a sentence, where they open a reply (Well, ...) |
only_after |
class attribute | Connectors that count inside a sentence only after these words |
read_through_marks |
class attribute | Connectors whose rules read the words before and after them through a punctuation mark: a comma always separates a question word from the verb before it (asked, why) |
split_by_marks |
class attribute | Connectors of several words that a punctuation mark between their words makes no connector |
pos_tags, pos_extra |
class attributes | Parts of speech of a one-word connector, CONNECTOR_POS of Universal Dependencies by default, and those allowed for a word on top of them |
not_after_pos |
class attribute | Parts of speech of the previous word that make a one-word connector no connector (a determiner: the before and the after) |
start_only_pos |
class attribute | Parts of speech of a one-word connector that counts only at the start of a sentence (a capitalized connector tagged as a proper noun) |
subordinators |
class attribute | Connectors that are subordinating conjunctions or prepositions besides the one-word ones tagged SCONJ or ADP (as soon as, in spite of), for is_subordinator |
classes, kinds |
class attributes | Classes and kinds of the dictionary; CONNECTOR_CLASSES and CONNECTOR_KINDS by default. The names inter and intra (CONNECTOR_PLACES) belong to the densities by place of CohesionStats and raise ParameterError when the class is defined |
messages |
class attribute | Messages of the errors by key; MESSAGES by default |
The words of the lists and the keys of pos_extra are normalized forms, while the other lists are keyed by the connector as the dictionary writes it. A rule that is not a collection of strings, or a mapping of strings to them, raises SourceTypeError when the class is defined.