Saltar a contenido

Estadísticas de cohesión

ests.cohesion_stats.CohesionStats

Descripción

Módulo para calcular las estadísticas de cohesión de un texto a la manera de Coh-Metrix y de su adaptación española Coh-Metrix-Esp: la repetición de sustantivos, de argumentos y de palabras con contenido entre oraciones, la información dada, la cohesión temporal y la densidad de los marcadores del discurso.

Las oraciones se comparan por lemas, y los rasgos vienen de la anotación de Universal Dependencies, así que la fuente tiene que estar anotada: una cadena se analiza con es_core_news_sm o con el pipeline indicado en nlp, y un Doc debe llevar las categorías gramaticales, que vienen de un morphologizer (o de un tagger con un attribute_ruler), y los lemas, que vienen de un lemmatizer; una fuente sin unas u otros levanta SourceError, y sin los lemas las repeticiones se calcularían sobre cadenas vacías, donde cada sustantivo se repite con todos los demás. Sin límites de oración - un pipeline sin analizador - las oraciones se toman del texto con SentsExtractor.

Un texto más largo que el max_length del pipeline - un millón de caracteres por defecto - levanta SourceError: divídalo en partes o suba max_length en un pipeline propio y páselo en nlp.

Nota

Las estadísticas se calculan al inicializar el objeto CohesionStats.

Parámetros

Parámetro Tipo Por defecto Descripción
source str/Doc - Fuente de datos (cadena u objeto Doc)
sents_extractor SentsExtractor None Herramienta de extracción de oraciones, usada con un Doc sin límites de oración
connectors dict[str, tuple[str, str]] None Diccionario de conectores: clase y tipo por conector; sin él se usa el diccionario de la biblioteca
nlp Language None Pipeline de spaCy que analiza una cadena; sin él se carga el modelo es_core_news_sm

Cohesión referencial

La repetición de Coh-Metrix: un par de oraciones es cohesivo cuando comparten el lema de un sustantivo (CRFNO), de un argumento - sustantivo o pronombre - (CRFAO) o de una palabra con contenido (CRFSO). Las medidas binarias dan la proporción de esos pares entre las oraciones contiguas y entre todos los pares del texto; las proporcionales (CRFCWO) dan el coeficiente de Dice medio de los conjuntos de lemas, 2·|A ∩ B| / (|A| + |B|).

Atributo Tipo Descripción
noun_overlap_adjacent float Proporción de pares contiguos que comparten un sustantivo
noun_overlap_all float Proporción de todos los pares que comparten un sustantivo
argument_overlap_adjacent float Proporción de pares contiguos que comparten un sustantivo o un pronombre
argument_overlap_all float Proporción de todos los pares que comparten un sustantivo o un pronombre
content_overlap_adjacent float Proporción de pares contiguos que comparten una palabra con contenido
content_overlap_all float Proporción de todos los pares que comparten una palabra con contenido
content_overlap_prop_adjacent float Proporción media de palabras con contenido compartidas en pares contiguos
content_overlap_prop_all float Proporción media de palabras con contenido compartidas en todos los pares
p_pronouns float Proporción de pronombres entre las palabras
pronoun_noun_ratio float Razón entre el número de pronombres y el de sustantivos
p_demonstratives float Proporción de demostrativos entre las palabras
p_given float Proporción de palabras con contenido cuyo lema ya apareció antes en el texto
tense_repetition float Proporción de pares contiguos con el mismo tiempo dominante
mood_repetition float Proporción de pares contiguos con el mismo modo dominante
temporal_cohesion float Media de la repetición del tiempo y del modo

Un sustantivo es NOUN o PROPN y una palabra con contenido es un NOUN, PROPN, ADJ, VERB o ADV. Un pronombre es un PRON o un determinante que señala algo - un posesivo (Poss=Yes) o uno demostrativo o personal (PronType=Dem, Prs) -, de modo que mi libro y este libro llevan un pronombre y el libro y cada libro no: los cuantificadores y los indefinidos (cada, todos, ningún, otro, cualquier) no señalan nada e inflarían alrededor de un quinto una medida de densidad anafórica. Un demostrativo lleva PronType=Dem.

Un argumento es un NOUN, PROPN o PRON, dejando fuera los determinantes aunque cuenten como pronombres: la repetición de argumentos de Coh-Metrix se hace con sustantivos y pronombres propiamente dichos, y el lema de este en dos oraciones no remite a la misma cosa.

La cohesión temporal sigue el SMTEMP de Coh-Metrix: de cada oración se toma el valor dominante del rasgo de sus verbos, y un par de oraciones contiguas cuenta como cohesivo cuando los valores coinciden. El español no tiene aspecto en Universal Dependencies, así que el modo ocupa su lugar junto al tiempo: el paso del indicativo al subjuntivo es lo que rompe el marco temporal de un texto español. Los pares en los que una de las oraciones no tiene ningún verbo con el rasgo se omiten, y un texto de menos de dos oraciones deja en nan todas las medidas de esta sección.

Conectores

Los marcadores del discurso de la clasificación de Martín Zorraquino y Portolés, 255 en ests/resources/connectors.tsv, en siete clases y dos tipos: primarios - conjunciones, locuciones conjuntivas y adverbios (porque, aunque, además) - y secundarios, las locuciones lexicalizadas (sin embargo, por lo tanto, es decir). La densidad se da por 1000 palabras.

Atributo Tipo Descripción
connectors float Conectores por 1000 palabras
connectors_causal float Conectores causales (porque, por lo tanto, así que)
connectors_adversative float Conectores adversativos (pero, sin embargo, en cambio)
connectors_concessive float Conectores concesivos (aunque, a pesar de, de todos modos)
connectors_temporal float Conectores temporales (cuando, a continuación, por último)
connectors_additive float Conectores aditivos (y, además, por otra parte)
connectors_conditional float Conectores condicionales (si, a menos que, de lo contrario)
connectors_reformulative float Conectores reformulativos (es decir, en resumen, por ejemplo)
connectors_primary float Conectores primarios por 1000 palabras
connectors_secondary float Conectores secundarios por 1000 palabras

Los conectores se buscan por sus formas en minúscula: en cada posición se toma el más largo, de modo que sin embargo no se rompe en sin, y los hallados no se solapan. Las apariciones están en el atributo connector_spans y su distribución en c_connectors.

Dos reglas dejan fuera los usos corrientes de esas palabras. Un conector de una palabra cuenta solo con una categoría de CONNECTOR_POS - conjunción, partícula, adverbio, adposición, interjección - y nunca tras un determinante, así que el antes y el después lleva un conector, y, y no tres; un nombre propio cuenta solo al principio de la oración, donde los modelos leen así un marcador (Primeramente, Concluyendo), de modo que el apellido de Ana, Luego y Mas firmaron no es conector. Y un marcador que además encabeza un sintagma preposicional se descarta ahí: antes de la reunión, después del informe, por encima de 80, al final de la línea, al principio de la oración, luego de la sesión y sobre todo el texto no cuentan nada, mientras que antes, firmó el acta, encima, no vino, al final, no vino y sobre todo cuando llueve cuentan su marcador.

En connectors puede pasarse un diccionario propio: del conector a su clase de CONNECTOR_CLASSES y su tipo de CONNECTOR_TYPES, y uno desconocido levanta ParameterError.

Advertencia

Un marcador español suele ser una locución hecha de palabras corrientes, y esas palabras se cuentan como cualquier otra: el sustantivo embargo de sin embargo y el sustantivo ejemplo de por ejemplo son sustantivos y palabras con contenido de su oración, y un texto que repite un marcador gana algo de repetición por ello. Medido sobre las páginas españolas de este sitio, la diferencia es inferior a 0,002 en todas las repeticiones, pero en un texto hecho de marcadores sería mayor.

Recuentos

Atributo Tipo Descripción
words tuple[tuple[str, ...], ...] Tupla de las palabras de cada oración
lemmas tuple[tuple[str, ...], ...] Tupla de los lemas de cada oración
n_sents int Número de oraciones con palabras
n_words int Número de palabras
n_nouns int Número de sustantivos
n_pronouns int Número de pronombres
n_demonstratives int Número de demostrativos
n_content_words int Número de palabras con contenido
n_given int Número de palabras con contenido cuyo lema ya apareció antes
n_connectors int Número de conectores
connector_spans tuple[Connector] Tupla de las apariciones de los conectores
c_connectors dict[str, int] Distribución de las apariciones por conector

Métodos

get_stats

Devuelve un diccionario con las estadísticas de cohesión calculadas.

Ejemplo

Código:

# Importar la biblioteca
from ests import CohesionStats

# Preparar los datos
text = (
    "El informe fue aprobado por la comisión. Sin embargo, el informe no resuelve "
    "el problema. Es decir, la comisión aplazó la decisión. Por lo tanto, el "
    "problema sigue abierto."
)

# Calcular las estadísticas
cs = CohesionStats(text)
cs.get_stats()

Resultado:

{'noun_overlap_adjacent': 0.3333333333333333,
'noun_overlap_all': 0.5,
'argument_overlap_adjacent': 0.3333333333333333,
'argument_overlap_all': 0.5,
'content_overlap_adjacent': 0.3333333333333333,
'content_overlap_all': 0.5,
'content_overlap_prop_adjacent': 0.08333333333333333,
'content_overlap_prop_all': 0.12037037037037039,
'p_pronouns': 0.034482758620689655,
'pronoun_noun_ratio': 0.09090909090909091,
'p_demonstratives': 0.0,
'p_given': 0.17647058823529413,
'tense_repetition': 0.0,
'mood_repetition': 1.0,
'temporal_cohesion': 0.5,
'connectors': 103.44827586206898,
'connectors_causal': 34.48275862068966,
'connectors_adversative': 34.48275862068966,
'connectors_concessive': 0.0,
'connectors_temporal': 0.0,
'connectors_additive': 0.0,
'connectors_conditional': 0.0,
'connectors_reformulative': 34.48275862068966,
'connectors_primary': 0.0,
'connectors_secondary': 103.44827586206898}

Las apariciones de los conectores están en un atributo propio:

cs.connector_spans
# (Connector(sent=1, start=0, end=2, text='sin embargo', cls='adversative', kind='secondary'),
#  Connector(sent=2, start=0, end=2, text='es decir', cls='reformulative', kind='secondary'),
#  Connector(sent=3, start=0, end=3, text='por lo tanto', cls='causal', kind='secondary'))

Muestra una tabla con las estadísticas de cohesión calculadas.

Para ilustrar el método reutilizamos el código del ejemplo anterior:

Ejemplo

Código:

...

# Mostrar la tabla de las estadísticas calculadas
cs.print_stats()

Resultado:

                        Statistic                         |  Value
--------------------------------------------------------------------
Noun overlap in adjacent sentences                        |   0.33
Noun overlap in all pairs of sentences                    |   0.50
Argument overlap in adjacent sentences                    |   0.33
Argument overlap in all pairs of sentences                |   0.50
Content word overlap in adjacent sentences                |   0.33
Content word overlap in all pairs of sentences            |   0.50
Share of shared content words in adjacent sentences       |   0.08
Share of shared content words in all pairs of sentences   |   0.12
Share of pronouns                                         |   0.03
Ratio of pronouns to nouns                                |   0.09
Share of demonstratives                                   |   0.00
Share of content words seen before                        |   0.18
Repetition of the tense in adjacent sentences             |   0.00
Repetition of the mood in adjacent sentences              |   1.00
Temporal cohesion                                         |   0.50
Connectors per 1000 words                                 |  103.45
Causal connectors per 1000 words                          |  34.48
Adversative connectors per 1000 words                     |  34.48
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                   |  34.48
Primary connectors per 1000 words                         |   0.00
Secondary connectors per 1000 words                       |  103.45

Búsqueda de conectores

ests.cohesion_stats.find_connectors(), ests.cohesion_stats.load_connectors()

find_connectors(words, connectors=None, sent_index=0, pos=None) halla los conectores de una sola oración y devuelve sus apariciones, y load_connectors() devuelve el diccionario de la biblioteca, la clase y el tipo por conector; el diccionario está en caché y es de solo lectura, así que un cambio se hace por el parámetro connectors y no sobre el objeto devuelto.

Ejemplo

from ests.cohesion_stats import find_connectors, load_connectors

find_connectors(["Sin", "embargo", "no", "vino"])
# [Connector(sent=0, start=0, end=2, text='sin embargo', cls='adversative', kind='secondary')]

find_connectors(["El", "antes", "y", "el", "después"], pos=["DET", "NOUN", "CCONJ", "DET", "NOUN"])
# [Connector(sent=0, start=2, end=3, text='y', cls='additive', kind='primary')]

load_connectors()["por lo tanto"]
# ('causal', 'secondary')