# ¿Cómo puedo extraer información métrica de un corpus en verso? Herramientas de análisis métrico y rimático.
## La experiencia de DISCO

Pablo Ruiz, Clara I. Martínez Cantón

► To cite this version:

Pablo Ruiz, Clara I. Martínez Cantón. ¿Cómo puedo extraer información métrica de un corpus en verso? Herramientas de análisis métrico y rimático. La experiencia de DISCO. Clara Martínez; Rocío Ortuño; Antonio Huertas. Las humanidades digitales en la enseñanza de las literaturas hispánicas. Aplicaciones prácticas, Peter Lang, pp.329-359, 2023, 10.3726/b21145. hal-04747963

HAL Id: hal-04747963

https://hal.science/hal-04747963v1

Submitted on 22 Oct 2024

HAL is a multi-disciplinary open access
archive for the deposit and dissemination of sci-
entific research documents, whether they are pub-
lished or not. The documents may come from
teaching and research institutions in France or
abroad, or from public or private research centers.

L'archive ouverte pluridisciplinaire HAL, est
destinée au dépôt et à la diffusion de documents
scientifiques de niveau recherche, publiés ou non,
émanant des établissements d'enseignement et de
recherche français ou étrangers, des laboratoires
publics ou privés.

<figure><img src="image_1.png" /></figure>

Distributed under a Creative Commons Attribution 4.0 International License
# ¿Cómo puedo extraer información métrica de un corpus en verso? Herramientas de análisis métrico y rimático. La experiencia de DISCO

Pablo RUIZ FABO

Université de Strasbourg
ruizfabo@unistra.fr

https://orcid.org/0000-0002-4349-4835

Clara I. MARTÍNEZ CANTÓN

UNED

cimartinez@flog.uned.es

https://orcid.org/0000-0003-0781-2418

**Resumen:** Los textos en verso presentan, además de la información de contenido que podemos encontrar en un texto cualquiera, una información adicional ligada a su forma y ritmo. Es lo que se ha estudiado tradicionalmente desde la métrica. Las herramientas digitales son de gran ayuda para extraer información métrica de textos en verso. El análisis métrico y rimático automático por medio de herramientas digitales da acceso a una información muy valiosa en el análisis literario de un autor, época, escuela, etc., que, aplicada a grandes corpus, resultaba prácticamente inaprensible de manera manual. Además, el uso de estas herramientas exige una reflexión sobre la teoría métrica que queremos utilizar en nuestro corpus y suponen una formalización y una puesta en práctica de la teoría a gran escala, lo que puede implicar un replanteamiento de ciertas categorías. En este capítulo se presentan distintas herramientas para estos fines y se proponen ejercicios prácticos para abordar la silabificación, el análisis acentual, el rimático y el de encabalgamiento en textos en verso.

**Palabras clave:** Verso. Métrica. Escansión silábica. Rima. Análisis métrico. Encabalgamiento. Acento

**NOTA:** Python funciona con indentación, que debe preservarse siempre tal y como aparece en este capítulo y como puede comprobarse en los ejemplos dados para este capítulo en el GitHub.
# 1. VERSO Y HUMANIDADES DIGITALES, UNA RELACIÓN PRIVILEGIADA

Los estudios literarios han llegado relativamente tarde al giro computacional que se ha ido dando en todas las ciencias. Esto puede ser justificado por diferentes causas circunstanciales, pero quizás una de las principales sea su propia naturaleza. Si bien la investigación en ciencia se basa en datos, y las herramientas ayudan a recogerlos, clasificarlos, analizarlos, etc.; la investigación en Humanidades se ha caracterizado tradicionalmente por ser crítica y hermenéutica, es decir, hay una labor de interpretación, de reflexión y una argumentación basada en conceptos aportados por otros estudios. Juega una labor fundamental la tradición histórica de una disciplina.

Sin embargo, hay ciertas disciplinas humanísticas en las que los métodos han estado desde el principio más cerca de lo que llamamos humanidades digitales. Es el caso de la lingüística o incluso la geografía, que ya trabajaban desde antes de la digitalización con unos métodos mucho más científicos.

La propia naturaleza del verso —“Conjunto de palabras sujetas a medida y cadencia, o solo a cadencia”— según la RAE, hace que tradicionalmente, desde la métrica, se haya cuantificado esa medida y se hayan realizado estudios estádísticos sobre ella. El verso exige una recurrencia periódica de elementos como el número de sílabas, posición de acentos o, al menos, de pausas en el discurso<fnref n="1" />. Podríamos decir que la métrica es una disciplina que ya maneja datos formales, por lo que la utilidad de herramientas que nos ayuden en el análisis del verso es clara (punto de vista también recogido en Bories et al., 2022, p. 5).

Quizás este sea el motivo por el que los análisis automáticos de la métrica del verso comienzan en épocas muy tempranas (por ejemplo, Newman, 1986). Logan (1988) recoge ya en la década de 1980 algunos de los primeros programas realizados para el inglés. Estos tipos de análisis son más dificultosos de lo que pueden parecer, en parte porque dependen profundamente de la lengua que se esté analizando y su prosodia. Además, se debe tener en cuenta la tradición métrica y los tipos de versificación utilizados en ella, así como la historia de esa tradición, ya que no será lo mismo un poema acentual en inglés, una *nursery rhyme*, por ejemplo, que un poema en verso libre de Walt Whitman, aunque los

<footnote n="1">1 Jakobson, hablaba de que la función poética proyecta “el principio de la equivalencia del eje de selección al eje de combinación” (Jakobson, 1975, p. 360), haciendo de esta recurrencia lo más significativo del lenguaje literario. El verso sería el lugar donde más fácilmente se ve esta recurrencia.</footnote>
dos ellos estén escritos en la misma lengua. Incluso dentro de una misma lengua habrá tipos de verso en los que ciertos rasgos sean relevantes y para otros no lo será (el acento en español es relevante para el endecasílabo, pero no lo es —no de la misma manera— en el octosílabo).

Esto hace que, al contrario de lo que sucede con otros tipos de herramientas de análisis literario, las dedicadas al verso sean específicas para cada idioma. Aunque las tecnologías y soluciones para este análisis sean las mismas o semeljantes, exigen una aplicación específica para cada idioma y para cada tipo de versificación.

El análisis métrico de corpus poéticos se ha utilizado tradicionalmente para responder preguntas literarias relacionadas con el estilo poético de un autor (Domínguez Caparrós, 1990, 2002; Martínez Cantón, 2011), de una escuela, de una época, etc (Gómez Bravo, 1998; Hrushovski, 1960; Utrera Torremocha, 2001). También incluso para responder a preguntas lingüísticas sobre evolución en la pronunciación de ciertos fonemas, la variación lingüística, etc. (Bermúdez Sabel, 2019, pp. 110-111) Las posibilidades que brinda el rápido análisis automático han hecho que se aplique también al reconocimiento de autoría (Plecháč, 2021), asociación entre forma poética y motivos temáticos (Šeļa, Plecháč, y Lassche, 2022) y otros campos. Todo esto sugiere una gran utilidad del análisis automático del verso (ver también Plecháč, Scherr, Skulacheva, Bermúdez-Sabel y Kolár, 2019).

## 2. ANÁLISIS AUTOMÁTICO DEL VERSO EN ESPAÑOL. SÍLABAS Y ACENTOS

Como adelantábamos en el epígrafe anterior el análisis métrico es dependiente de la lengua y del tipo de verso utilizado Por ello, si nos enfrentamos a un corpus en verso deberemos primero ser conscientes de qué tipo de métrica va a utilizar y si las herramientas que vamos a utilizar nos van a ser útiles.

En español los elementos métricos aceptados unánimemente como fundamentales son el número de sílabas en el verso, la posición de los acentos (sobre todo para el endecasílabo), la pausa y la rima.

En español, las tareas de automatizar el cómputo de sílabas y de asignar sílaba tónica y átona a esas sílabas se han realizado normalmente de manera conjunta, dado que no hay una métrica puramente acentual (muy raras excepciones).

Aunque las particularidades de cada lengua hacen que los programas no puedan ser los mismos sí lo son los métodos. Se suele distinguir entre dos enfoques:
* Escansión basada en reglas lingüístico-prosódicas. Se basan, normalmente, en programas ya existentes de Procesamiento del Lenguaje Natural (PLN) que realizan la división en sílabas gramaticales y otros análisis relacionados como el etiquetado de funciones sintácticas o la asignación de acentos.

* Escansión basada en datos, es decir, con base estadística y aprendizaje automático (mediante redes neuronales u otros métodos de machine learning). Estas técnicas no tienen por qué basarse en reglas o realizar la división en sílabas (aunque pueden también utilizar estos métodos).

En el caso del español se ha propuesto también un enfoque (descrito más abajo) que realiza escansión sin silabificación automática previa, mediante la deteción directa de los acentos (Marco y Gonzalo, 2021). Según el resultado que queramos utilizaremos un tipo de herramientas u otro. Es decir, si por ejemplo queremos que sea visible la escansión silábica de cada verso no podremos elegir un programa que no efectúa una silabación previa a la escansión.

Los análisis automáticos serios de número de sílabas para cada verso comienzan en español en la década de los 2000. En esa fecha Pablo Gervás (2000) propuso un enfoque de programación lógica (con reglas) para el análisis de poemas españoles y evaluó dicho enfoque en un conjunto de sonetos del Siglo de Oro español. No hubo mucha continuidad para estas funciones de análisis de verso en esa época, pero los últimos años han traído un renovado interés que hace que nos encontremos con varias propuestas. En 2017 Borja Navarro-Colorado (2017) propone un programa de análisis silábico acentual de endecasílabos. Poco después, Agirrezabal, Alegria y Hulden (2017) propusieron un modelo de redes neuronales para predecir el patrón métrico De los versos que analizaba número de sílabas y acento. Dos de los sistemas más recientes de análisis de verso se han ofrecido desde la UNED. El primero es un sistema basado en reglas lingüísticas, llamado Rantanplan (De la Rosa, Pérez, Hernández, Ros, y González-Blanco, 2020). Primero efectúa un análisis morfológico con la librería spaCy (Honnibal et al., 2020) utilizando un modelo para español. Después silabifica, asigna tonicidad y posteriormente ajusta métricamente según las reglas dadas por conocimiento experto (a partir de teorías métricas). El programa tiene en cuenta el contexto del poema para cada verso. Así, en cada análisis de un verso se calculan sus posibilidades de análisis y posteriormente se contrasta con la longitud métrica esperada y las posiciones de acentos más comunes.

El segundo programa de análisis de verso es Jumper (Marco y Gonzalo, 2021). Este sistema se basa en la premisa de que, en español, la vocal es el núcleo de la sílaba e identifica su unidad; con ello se determina el número de sílabas. El acento se determina por las reglas ortográficas del español. Calcula posibles
hemistiquios y sus equivalencias de finales en versos mayores de 11 sílabas (Marco et al., 2021, p. 51739). Jumper no efectúa una silabificación léxica previa a la escansión, y tampoco realiza un etiquetado gramatical; no depende entonces de ninguna librería de procesamiento del lenguaje natural. Se ha mostrado (Marco y Gonzalo, 2021) que Jumper obtiene mejores resultados que las otras herramientas con el verso compuesto (en español, muy común en todo verso de más de 11 sílabas). Por esta razón, si nuestro corpus comporta verso compuesto, es conveniente aplicar esta herramienta para obtener los patrones métricos. Jumper ofrece una interfaz de fácil uso para análisis de poemas concretos, pero no para corpus extensos ya que el número de versos que acepta la interfaz es limitado; para analizar un volumen elevado de versos se debe utilizar a través de código en Python.

Por otra parte, muy recientemente, se ha presentado una nueva herramienta de escansión automática para verso castellano, LibEscansión (Sanz-Lázaro, 2022). Ha sido diseñada originalmente para el análisis de versos en obras de teatro áureo, pero funciona para todo tipo de poesía de metro regular. LibEscansión es capaz de escandir versos de metro variable aplicando ajustes silábicos y localizando acentos métricos. Proporciona el recuento silábico, núcleos silábicos, transcripción fonológica de las sílabas, rimas consonante y asonante, y ritmo acentual (Sanz-Lázaro, 2023, p. 239)<fnref n="2" />.

En el momento en el que se publica este libro, ninguno de los programas señalados cuenta con una interfaz gráfica de uso sencillo en la que podamos cargar un corpus amplio para obtener su análisis métrico. Para usar los programas nombrados sin limitaciones es necesario dar instrucciones a través de código o de línea de comandos.

Esto es lo que aprenderemos a hacer aquí en la sección 3. Hemos seleccionado para ello dos programas. Primeramente Rantanplan, que presenta una documentación más completa que otros programas y que da resultados de silabificación léxica, métrica y escansión (además el programa también permite detectar la rima, ver la sección 5.1). En segundo lugar, Jumper, cuya instalación es inmediata al no tener dependencias y cuyos resultados con verso compuesto son los mejores hoy en día.

Antes de comenzar el ejercicio, cabe mencionar nuestra experiencia de uso de analizadores de escansión. El corpus de sonetos DISCO (Ruiz Fabo et al.,

<footnote n="2">2 Por el momento no está todavía públicamente disponible. Otro software relacionado sí permite ya su uso y se encuentra en: https://github.com/fsanzl/libEscansion.</footnote>
2021) se etiquetó hasta su versión 3 con la herramienta de Navarro-Colorado (2017), que era la mejor disponible en el momento de comenzar el corpus. Los nuevos sonetos añadidos en la versión 4 se etiquetaron originalmente con la más reciente Rantanplan. Sin embargo, las versiones 4 y 5 del corpus añaden un buen número de sonetos modernistas, que incluyen una gran proporción de metros complejos. Dada la adecuación para estos metros de Jumper, el material añadido en la versión 5 se etiquetó con Jumper, con el que también se reetiquetaron los sonetos añadidos en la versión 4.

# 3. EJERCICIO PRÁCTICO DE ANÁLISIS SILÁBICO Y ACENTUAL

El ejercicio consiste en obtener la escansión primero para un sólo poema y después para una serie de poemas en un directorio. Se usan las herramientas Rantanplan y Jumper. Se hará con el lenguaje Python mediante la herramienta Jupyter Notebooks, que permite mezclar instrucciones en Python con texto (o con imágenes), lo cual es muy útil para compartir los resultados y explicar el código. Para usar el lenguaje Python, si no está ya instalado (versión ≥ 3.7), proponemos instalar la distribución Anaconda siguiendo su documentación<fnref n="3" />.

## 3.1. Primeros pasos

Una vez instalado Anaconda, se puede acceder a los notebooks Jupyter desde los menús del sistema correspondiente. Por ejemplo, en Windows, en el grupo de Anaconda desde el menú de inicio (figura 1a), se puede abrir directamente la aplicación Jupyter Notebook (figura 1b). Otra opción es abrir Anaconda Navigator y una vez abierto arrancar Jupyter Notebook. Un notebook con el ejercicio práctico resuelto se encuentra en el repositorio GitHub del capítulo<fnref n="4" />.

<footnote n="3">3. Se encuentra el modo de instalar en Windows, Mac o Linux a partir de la página siguiente: https://docs.anaconda.com/anaconda/install/.</footnote>

<footnote n="4">4. Accesible desde: https://github.com/HD-aula-Literatura/III-8-Verso/blob/main/etiquetado-escansion-rantanplan.ipynb.</footnote>
<figure><img src="image_2.png" /><figcaption>(a) Acceso a Jupyter Notebook desde el grupo de Anaconda desde el menú Inicio de Windows</figcaption></figure>

<figure><img src="image_3.png" /><figcaption>(c) Árbol de directorios una vez arrancado Jupyter</figcaption></figure>

<figure><img src="image_4.png" /><figcaption>(b) Acceso a Jupyter Notebooks desde Anaconda Navigator</figcaption></figure>

**Figura 1.** Acceder o crear un notebook con Jupyter Notebooks

Desde Jupyter Notebook, podemos acceder a notebooks existentes. Por ejemplo, si hemos bajado desde GitHub el repositorio correspondiente a esta actividad³ y lo hemos guardado dentro de la carpeta *Documentos* (usando Windows), en un subdirectorio llamado *III-8-Verso*, tendremos acceso al *notebook* desde el árbol de acceso (similar al que se muestra en la figura 1c). El notebook en GitHub da detalles omitidos aquí por espacio<fnref n="5" />.

## 3.2. Instalar las herramientas y sus dependencias

Los **notebooks Jupyter** se han usado ya en el capítulo 3 de la parte II, sobre extracción de datos a partir de fuentes web<fnref n="6" />. En resumen, estos *notebook* se dividen en celdas. Las celdas pueden ser ejecutables (con código Python o

<footnote n="5">5 Las instrucciones siguientes se han ejecutado con la versión 3.7 de Python, que es la que figura en la documentación de Rantanplan (https://rantanplan.readthedocs.io/). El notebook muestra cómo crear un entorno Python 3.7 con Anaconda.</footnote>

<footnote n="6">6 Unas líneas sobre su uso están en https://github.com/HD-aula-Literatura/II-2-scraping/tree/main/02-extraccion-con-python#%C3%B3mo-usar-los-materiales.</footnote>
código de la línea de comandos del sistema) o de texto (incluido imágenes); el texto se puede dejar sin formatear o formateado con un lenguaje de etiquetado ligero intuitivo llamado markdown<fnref n="7" />.

Para instalar **Rantanplan**, instalaremos primero spaCy, librería de la que depende y que efectúa el análisis gramatical sobre el que se basa la detección de sílabas tónicas y átonas realizada por Rantanplan dentro del proceso de escansión. Rantanplan requiere la versión 2.2.4 de spaCy, que instalaremos con la instrucción (1) en una celda ejecutable de un notebook Jupyter. El signo de exclamación se debe a que es una instrucción no del lenguaje Python, sino de la línea de comandos del sistema.

(1) !pip install spacy==2.2.4

SpaCy tiene recursos lingüísticos específicos a cada lengua soportada para ciertas tareas. Deberemos instalar un modelo (conjunto de recursos) para español que sea compatible con la versión 2.2.4. Cabe advertir que el modelo más actualizado no es compatible con esta versión de spaCy, y que utilizaremos una instrucción específica, reflejada en (2), para descargar un modelo anterior dado su número de versión.

(2) !pip install -U https://github.com/explosion/spacy-models/releases/download/es_core_news_md-2.2.5/es_core_news_md-2.2.5.tar.gz

Instalamos también un módulo adicional relacionado con el análisis gramatical:

(3a) !pip install spacy_affixes

(3b) !python -m spacy_affixes download es

Después de lo anterior podemos finalmente instalar Rantanplan:

(4) !pip install rantanplan

En cuanto a **Jumper**, no requiere la instalación de dependencias, lo descargaremos y lo usaremos (ver 3.4) desde cualquier entorno Python, como p. ej. desde

<footnote n="7">7 https://docs.github.com/es/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax.</footnote>
un *notebook Jupyter*, como hacemos en este capítulo. Jumper no se ha añadido al repositorio de módulos de Python (*Python Package Index*), con lo que en vez de instalarlo con *pip*, lo descargaremos directamente desde GitHub. Para esto, las personas que usan la herramienta *git* (cuya descripción queda fuera del perímetro de este capítulo) lo pueden hacer del modo habitual con *git clone*. En caso contrario, se puede descargar el código con un navegador web, desde el repositorio en GitHub<fnref n="8" />. Como se ve en la figura 2, con el botón *Code* tendremos acceso a una opción *Download ZIP* para descargar un archivo comprimido con el código. Una vez descomprimido este archivo, se verán los contenidos de la figura 3.

<figure><img src="image_5.png" /><figcaption>**Figura 2.** Interfaz web de GitHub mostrando el repositorio de Jumper. Con los botones *Code* y después *Download ZIP* se descarga el código</figcaption></figure>

<figure><img src="image_6.png" /><figcaption>**Figura 3.** Contenido de la aplicación Jumper tal como se ve en el explorador de Windows</figcaption></figure>

<footnote n="8">8 https://github.com/grmarco/jumper.</footnote>
### 3.3. Escansión con Rantanplan

#### 3.3.1. Escansión de un solo poema

Esta sección presupone que se han seguido los pasos en 3.1 y 3.2 para instalar la distribución Anaconda de Python así como la herramienta Rantanplan y sus dependencias.

Para poder usar Rantanplan, debemos importar la libería y la función que lanza la escansión (5):

(5) `import rantanplan`
`from rantanplan.core import get_scansion`

Declaramos después una variable, aquí llamada `texto-poema`, y le asignamos como valor, con el signo igual (`=`), el texto del poema a analizar (6). Como el valor es una cadena de texto (tipo `str` en Python), hay que escribir este texto entre comillas; se han usado triples comillas porque permiten expresar un texto dentro del cual hay saltos de línea, como es el caso después de cada verso de un poema. Se ha usado un poema de Evangelina Guerrero, poeta filipina presente en el corpus DISCO<fnref n="9" />.

(6) `texto-poema = """Rosas sangrantes sobre el mar desflora el sol que dice adioses en la tarde, riman las aguas su canción sonora, bajo nubes de fuego el poniente arde. Vibran las cañas al chocar del viento, formando extraña y triste sinfonía, y la palmera altiva en vaivén lento es una glauca nota de armonía. Una barca se aleja lentamente, una estela de luz, un vago canto, sombras que pasan sobre el quieto mar; Y las horas se van pausadamente, mientras vierte la luz su último encanto en un intenso, pálido llamear. """

<footnote n="9">9 https://github.com/pruizf/disco/blob/v4/txt/20th/per-sonnet/disco004t_0090.txt.</footnote>
Para la escansión, usamos la función `get_scansion()`, que toma como argumento (dentro de los paréntesis) el nombre de la variable que contiene el texto del poema (7). Se asigna el resultado de la escansión a una variable, que aquí se ha llamado `resultado` pero que se podría llamar de cualquier otra forma permitida en Python:

(7) `resultado = get_scansion(texto-poema)`

El resultado de la escansión (asignado a `resultado`) contiene varios tipos de información. Vemos aquí los contenidos más importantes del resultado y cómo explotarlos. El resultado contiene una lista de valores (un valor por verso) con una estructura concreta, este tipo de estructura se conoce como *diccionario* en Python (tipo `dict`). Un diccionario está estructurado según pares de clave-valor. Describimos las claves que nos interesan más directamente:

* **tokens**: contiene a su vez una lista de diccionarios, cada uno de los cuales tienen una clave `word`. El valor de `word` es a su vez una lista de diccionarios, uno por sílaba. Dentro de éstos, el valor de la clave `syllable` nos da la secuencia ortográfica para cada sílaba léxica del poema. P. ej. en el verso 4, veremos que los valores de `syllable` dentro de cada diccionario `word` son (separados con un guion): `ba-jo`, `nu-bes`, `de`, `fue-go`, `el`, `po-nien-te`, `ar-de`.

* **phonological_groups**: Representa la silabificación métrica mediante una lista de diccionarios. La clave `syllable` de cada diccionario permite acceder a las sílabas métricas. Por ejemplo, en el verso 4, los valores de estas claves `syllable` son (separados con guion): `ba-jo-nu-bes-de-fue-goel-po-nien-tear-de` (sinalefas destacadas en negrita)

* **rhythm**: Es también un diccionario. Nos interesan sus claves `stress` y `length`.

* **stress**: El patrón métrico, con un signo más (+) para sílabas métricas tónicas y un signo menos (-) para las átonas. En el verso 4 el patrón es `---+---+--`, con acentos en las sílabas 3 y 6, el acento obligatorio en la 10 y un acento antirrítmico en la 9.

* **length**: Número de sílabas métricas del verso (en este poema siempre 11).

La forma de extraer los patrones métricos y otras informaciones de la respuesta de Rantanplan se describe más en detalle en el notebook del capítulo. Aquí introducimos las instrucciones básicas para extraer los patrones.
<table><thead><tr><th>(9a)</th><th>(9b)</th></tr></thead><tbody><tr><td>for indice, verso in enumerate(resultado):</td><td>1 +--+---+--+</td></tr><tr><td>escansion = verso["rhythm"]["stress"]</td><td>2 -+--+---+--</td></tr><tr><td>print(indice+1, escansion)</td><td>3 +--+---+--+</td></tr><tr><td></td><td>4 ---+---+--</td></tr><tr><td></td><td>5 +--+---+--</td></tr><tr><td></td><td>6 -+--+---+--</td></tr><tr><td></td><td>7 ---+--+--</td></tr><tr><td></td><td>8 ++--+---+--</td></tr><tr><td></td><td>9 +--+--+--</td></tr><tr><td></td><td>10 +--+--+--</td></tr><tr><td></td><td>11 +--+--+--</td></tr><tr><td></td><td>12 ---+--+--</td></tr><tr><td></td><td>13 ---+--+--</td></tr><tr><td></td><td>14 -+--+--</td></tr></tbody></table>

Otra forma de mejorar la salida consiste en representar los patrones con cifras en vez de con signos **más y menos**, con el código en (10a), cuyo resultado está en (10b). Se han separado los números de verso del patrón métrico con una tabulación, \t. El código nuevo para asignar los números de verso se explica en el repositorio.

<table><thead><tr><th>(10a)</th><th>(10b)</th></tr></thead><tbody><tr><td>for indice, verso in enumerate(resultado):</td><td>1 1 4 8 10</td></tr><tr><td>escansion = verso["rhythm"]["stress"]</td><td>2 2 4 6 10</td></tr><tr><td>escansion_cifras = " ".join(</td><td>3 1 4 8 10</td></tr><tr><td>[str(i+1) for i, sig</td><td>4 3 6 9 10</td></tr><tr><td>in enumerate(escansion)</td><td>5 1 4 8 10</td></tr><tr><td>if sig == "+"]</td><td>6 2 4 6 10</td></tr><tr><td>print(f"{indice+1}\t{escansion_cifras}")</td><td>7 4 6 9 10</td></tr><tr><td></td><td>8 1 2 4 6 10</td></tr><tr><td></td><td>9 1 3 6 8 10</td></tr><tr><td></td><td>10 1 3 6 7 8 10</td></tr><tr><td></td><td>11 1 4 8 10</td></tr><tr><td></td><td>12 3 6 8 10</td></tr><tr><td></td><td>13 3 6 7 10</td></tr><tr><td></td><td>14 2 4 6 10</td></tr></tbody></table>
### 3.3.2. Escansión de un corpus de poemas

Podemos reproducir la misma operación sobre los diferentes archivos de un directorio, cada uno de los cuales contendrá un poema. La figura 4 muestra los resultados que se pueden obtener; se ha optado por asignar un identificador a cada poema y mostrar también el número de verso, así como el incipit y los resultados de escansión. El código para hacerlo está en el notebook ya citado para este ejercicio.

<table><caption>**Figura 4:** Resultados de escansión para un corpus de varios poemas. Se muestra el principio del archivo de datos (dataframe) correspondiente, abierto con LibreOffice</caption><thead><tr><th></th><th>A</th><th>B</th><th>C</th><th>D</th><th>E</th><th>F</th></tr><tr><th></th><th>numPoema</th><th>incipit</th><th>numVerso</th><th>verso</th><th>escanSig</th><th>escanNum</th></tr></thead><tbody><tr><td>2</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>++++</td><td>1 4 8 10</td></tr><tr><td>3</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>2</td><td>el sol que dice adioses en la tarde,</td><td>++++</td><td>2 4 6 10</td></tr><tr><td>4</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>3</td><td>riman las aguas su canción sonora,</td><td>++++</td><td>1 4 8 10</td></tr><tr><td>5</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>4</td><td>bajo nubes de fuego el poniente arde,</td><td>++++</td><td>3 6 9 10</td></tr><tr><td>6</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>5</td><td>Vibran las cañas al chocar del viento,</td><td>++++</td><td>1 4 8 10</td></tr><tr><td>7</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>6</td><td>formando extraña y triste sinfonia,</td><td>++++</td><td>2 4 6 10</td></tr><tr><td>8</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>7</td><td>y la palmera alta en valvén lento,</td><td>++++</td><td>4 6 9 10</td></tr><tr><td>9</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>8</td><td>es una glauca nota de armonía,</td><td>++++</td><td>1 2 4 6 10</td></tr><tr><td>10</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>9</td><td>Una barca se aleja lentamente,</td><td>++++</td><td>1 3 6 8 10</td></tr><tr><td>11</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>10</td><td>una estela de luz, un vago canto,</td><td>++++</td><td>1 3 6 7 8 10</td></tr><tr><td>12</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>11</td><td>sombras que pasan sobre el quieto mar;</td><td>++++</td><td>1 4 8 10</td></tr><tr><td>13</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>12</td><td>Y las horas se van pausadamente,</td><td>++++</td><td>3 6 8 10</td></tr><tr><td>14</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>13</td><td>mientras vierte la luz su último encanto,</td><td>++++</td><td>3 6 7 10</td></tr><tr><td>15</td><td>1</td><td>Rosas sangrantes sobre el mar desflora</td><td>14</td><td>en un intenso, pálido llamear.</td><td>++++</td><td>2 4 6 10</td></tr><tr><td>16</td><td>2</td><td>Como un vigía que en la noche vela</td><td>1</td><td>Como un vigía que en la noche vela</td><td>++++</td><td>2 4 8 10</td></tr><tr><td>17</td><td>2</td><td>Como un vigía que en la noche vela</td><td>2</td><td>las almas el perdón tu amor enlaza,</td><td>++++</td><td>2 6 8 10</td></tr><tr><td>18</td><td>2</td><td>Como un vigía que en la noche vela</td><td>3</td><td>y allí a tus plantas fugitiva estela</td><td>++++</td><td>2 4 8 10</td></tr><tr><td>19</td><td>2</td><td>Como un vigía que en la noche vela</td><td>4</td><td>de lágrimas, la ignota angustia traza,</td><td>++++</td><td>2 6 8 10</td></tr><tr><td>20</td><td>2</td><td>Como un vigía que en la noche vela</td><td>5</td><td>de lágrimas, la ignota angustia traza,</td><td>++++</td><td>2 4 8 10</td></tr></tbody></table>

## 3.4. Escansión con Jumper

Esta sección presupone que se han seguido los pasos en 3.1 y 3.2 para instalar la distribución Anaconda de Python y descargar la herramienta Jumper.

### 3.4.1. Escansión con la interfaz gráfica

Una forma de acceder a esta interfaz gráfica es a partir de una línea de comandos (también conocida como consola o terminal) del sistema de explotación que se use. Aquí hemos tomado Windows como ejemplo, y usaremos la consola Anaconda Prompt que forma parte de la distribución Anaconda (un entorno para programas de Python). Al abrir esta consola, un entorno de Python estará accesible automáticamente. En Mac o Linux se puede usar el terminal y activar el entorno por defecto de Python dentro de Anaconda, con el comando `conda activate base`. En Windows, Anaconda Prompt está disponible a partir del menú de inicio, como en la figura 5 (Windows 10).
<figure><img src="image_7.png" /><figcaption>**Figura 5.** Localización de la consola Anaconda Prompt en el menú de inicio de Windows (10)</figcaption></figure>

Con la consola de Anaconda Prompt, debemos desplazarnos al directorio (carpeta) donde está Jumper. Por ejemplo, si Jumper está en `C:\tests\jumper`, como es el caso en la figura 6, donde la barra de direcciones de Windows muestra la ruta `C:\tests\jumper`, deberemos ir a esta carpeta con la consola. Para esto, introducimos el comando `cd /d c:\tests\jumper`, como se ve en la figura 7.

Describimos en detalle el contenido de lo que se muestra en la consola. La línea **(base) C:\Users\utiltest>cd /d c:\tests\jumper** tiene el siguiente significado.

* **(base)**: Muestra el entorno de Python en el que estamos trabajando, que, por defecto, al abrir una consola de Anaconda, es el entorno llamado **base**

* **C:\Users\utiltest**: Directorio en el que la consola se abre. Corresponde al directorio personal del usuario que ha ejecutado Anaconda Prompt. En el ordenador utilizado, el nombre de usuario es **utiltest**, por eso la ruta que la consola muestra para el directorio personal o **home** del usuario es **C:\Users\utiltest**.

* `>: Separador que indica que la ruta del directorio actual termina, en una consola de Windows (así como en una consola de Mac o Linux típicamente el separador es el signo dólar $). Después de este separador podemos introducir nuestras instrucciones o comandos.

* `cd /d c:\tests\jumper`: Comando `cd` (change directory o cambiar directorio), seguido del directorio que se quiere alcanzar, es decir `C:\`
`tests\jumper` (las rutas en Windows, contrariamente a Mac o Linux, no son sensibles a la diferencia entre mayúscula y minúscula, con lo que da igual `c: o C:`). Se ha añadido la opción `/d` (que no sería obligatoria en este caso) por la razón siguiente: Con la opción `/d`, podemos desplazarnos directamente a directorios que están en otra unidad de disco (p. ej. un directorio que estuviera en la unidad F). Aquí partimos de un directorio que está dentro de la unidad C para ir a otro directorio de la misma unidad, con lo que la opción `/d` no sería necesaria.

Después de confirmar con la tecla Enter el comando `cd c:\tests\jumper`, la parte que precede al separador `>` en la consola cambia. Ahora esta parte muestra (`base`) `C:\tests\jumper`, como se ve en la figura 8. Esto quiere decir que ya estamos dentro del directorio deseado, a partir de la consola.

En este directorio se encuentra el módulo de la interfaz gráfica de Jumper, que se llama `jumper_app.py`. Para poder usar la interfaz, introducimos en la consola el comando siguiente: `python jumper_app.py` (ver figura 8). Esto abrirá la interfaz, que se muestra en la figura 9.

<figure><img src="image_8.png" /><figcaption>**Figura 6.** Aplicación Jumper, en este caso guardada en la ruta `C:\tests\jumper`, como se ve en la barra de direcciones</figcaption></figure>

<figure><img src="image_9.png" /><figcaption>**Figura 7.** Comando `cd` para ir al directorio donde está la aplicación Jumper</figcaption></figure>
<figure><img src="image_10.png" /><figcaption>**Figura 8.** Comando para lanzar la aplicación Jumper</figcaption></figure>

<figure><img src="image_11.png" /><figcaption>**Figura 9.** Interfaz de Jumper tal y como se muestra al abrir la aplicación</figcaption></figure>

La interfaz cuenta con menús intuitivos. Después de introducir un texto en la caja de texto *Poema*, activamos su análisis métrico desde el menú *Análisis*, y el resultado se mostrará en la caja *Análisis* de la parte inferior. En el menú *Ayuda* hay información sobre el funcionamiento de la interfaz. Desde el menú *Archivo* podemos guardar los resultados de análisis.

En cuanto a los resultados que da la interfaz, se ve un ejemplo en la figura 10; el texto es el mismo que se ha usado en el resto del capítulo. Los resultados incluyen el número de sílabas métricas para cada verso, las posiciones acentuadas, las posiciones acentuadas pero ignorando los acentos extrarrítmicos y una clasificación de cada verso según su patrón métrico, usando, como se indica en Marco y Gonzalo (2021), la tipología de Jauralde (2020). La última columna muestra la ratio de coincidencia entre el tipo métrico de la antepenúltima columna y el patrón de posiciones acentuadas propuesto por Jumper. Cuando la coincidencia en un verso es 100, la línea que corresponde al verso dentro de la tabla de resultados se muestra en color verde.
<figure><img src="image_12.png" /><figcaption>**Figura 10.** Resultados de análisis de Jumper</figcaption></figure>

Para obtener los resultados de un gran número de poemas, en vez de utilizar la interfaz gráfica, utilizaremos, de forma similar a lo que se ha visto para Rantanplan, código en Python. Esto es el objeto de las secciones 3.4.2 y 3.4.3.

### 3.4.2. Escansión con código Python para un solo poema

Podemos darle a Jumper el contenido de un solo poema o de varios, en una sola cadena de texto, y la herramienta gestionará la escansión de cada uno. Esta cadena de texto puede darse dentro de una variable en el propio código o bien hacer que Python lea el texto a partir de un archivo. Vamos a ver un ejemplo con un notebook Jupyter, que crearemos en el mismo directorio en el que está Jumper (como en los ejemplos anteriores, usamos `c:\tests\jumper`). Podemos arrancar el entorno Jupyter Notebook desde la consola, abierta en el directorio deseado como se ha visto en 3.4.1, con el comando `jupyter notebook` (figura 11).

<figure><img src="image_13.png" /><figcaption>**Figura 11.** Arrancar el entorno Jupyter Notebook en el directorio de Jumper</figcaption></figure>

Esto abrirá, en el navegador web, una interfaz que nos da acceso al entorno Jupyter Notebook. Podemos ver los contenidos del directorio en que se ha abierto el entorno y podemos crear ahí un notebook, como se ve en la figura 12. El notebook completo está disponible en GitHub y contiene detalles omitidos aquí por razones de espacio<fnref n="10" />.

<footnote n="10">10 https://github.com/HD-aula-Literatura/III-8-Verso/blob/main/etiquetado-escans-ion-jumper.ipynb.</footnote>
<figure><img src="image_14.png" /><figcaption>**Figura 12.** Interfaz del entorno Jupyter Notebook tras abrirlo en el directorio donde está Jumper. Con el botón *New* y *Python 3* creamos un nuevo notebook</figcaption></figure>

En el notebook, en una celda de código vamos a introducir las instrucciones de (11). Primero, con `import jumper`, importamos el módulo que contiene el algoritmo de Jumper; el módulo se llama `jumper.py`. Esto funciona porque el notebook y el módulo están en el mismo directorio. Declaramos después una variable, aquí llamada `texto-poema`, que contiene el texto del poema en una cadena de caracteres; se dieron más detalles sobre esto en (6). Después aplicamos la escansión de Jumper con la función `escandir_texto()`, que está definida en el módulo `jumper`. Al aplicar la función se le ha pasado como argumento la variable `texto-poema`, que contiene el texto del poema: `escandir_texto(texto-poema)`. El resultado de la escansión se ha asignado a la variable `resultado`.
(11)

import jumper

texto-poema = """Rosas sangrantes sobre el mar desflora
el sol que dice adioses en la tarde,
riman las aguas su canción sonora,
bajo nubes de fuego el poniente arde.

Vibran las cañas al chocar del viento,
formando extraña y triste sinfonía,
y la palmera altiva en vaivén lento
es una glauca nota de armonía.

Una barca se aleja lentamente,
una estela de luz, un vago canto,
sombras que pasan sobre el quieto mar;

Y las horas se van pausadamente,
mientras vierte la luz su último encanto
en un intenso, pálido llamear. """

Resultado = jumper.escandir_texto(texto-poema)

Los resultados de escansión, asignados a la variable *Resultado* en el código de (11), consisten en una lista de listas de valores, una lista de valores para cada verso. Si mostramos la lista de valores que corresponde al primer verso, con la instrucción *print(resultado[0]*) en una celda del notebook, veremos la información en (12). Los elementos de la lista están separados por comas (si bien algunos de los elementos son a su vez listas, como el cuarto y quinto elemento, cuyo valor es en los dos casos [1, 4, 8, 10]; este valor corresponde a las posiciones de las sílabas acentuadas con y sin acentos extrarrítmicos (en este verso no hay diferencia entre los dos patrones)). Como se puede observar, el orden de los elementos corresponde al orden de las columnas de resultados que se veía en la interfaz de Jumper (figura 10). Los campos de resultados son el tercero de la lista, que contiene el número de sílabas métricas (aquí, 11), el cuarto y quinto ya citados, el sexto, con el patrón métrico clasificado como se ha descrito en 3.4.1, y un último campo con un valor entre 0 y 1, que significa la ratio de coincidencia de las posiciones acentuadas con el tipo métrico propuesto
por la herramienta (en la interfaz este valor se multiplica por 100 con lo que la coincidencia plena se representa con 100 en vez de con 1).

(12)
['Rosas sangrantes sobre el mar desflora',
'Rosas sangrantes sobre el mar desflora',
11,
[1, 4, 8, 10],
[1, 4, 8, 10],
'Endecasílabo sáfico puro pleno',
1.0]

Podemos crear un bucle de código para mostrar los resultados en forma de tabla, con las informaciones para cada verso en una línea diferente, como en (13). Aquí se muestra el código para destacar que con poco trabajo se pueden obtener resultados listos a analizar, pero las explicaciones de su funcionamiento se encuentran en el notebook completo en GitHub.¹⁰ El resultado del código en (13) se muestra en la figura 13. En el notebook completo en GitHub se muestra código para hacer esta salida más legible.

(13)
for infos in resultado:
    print("\t".join([str(x) for x in infos[1:]]))

Rosas sangrantes sobre el mar desflora 11 [1, 4, 8, 10] [1, 4, 8, 10] Endecasílabo sáfico puro pleno 1.0
el sol que dice adioses en la tarde, 11 [2, 4, 6, 10] [2, 4, 6, 10] Endecasílabo heroico corto 1.0
riman las aguas su canción sonora, 11 [1, 4, 8, 10] [1, 4, 8, 10] Endecasílabo sáfico puro pleno 1.0
bajo nubes de fuego el poniente arde. 11 [3, 6, 9, 10] [3, 6, 10] Endecasílabo melódico puro 0.9
Vibran las cañas al chocar del viento, 11 [1, 4, 8, 10] [1, 4, 8, 10] Endecasílabo sáfico puro pleno 1.0
formando extraña y triste sinfonia, 11 [2, 4, 6, 10] [2, 4, 6, 10] Endecasílabo heroico corto 1.0
y la palmera altiva en vaivén lento 11 [4, 6, 9, 10] [4, 6, 10] Endecasílabo sáfico corto 0.9
es una glauca nota de armonía. 11 [1, 2, 4, 6, 10] [2, 4, 6, 10] Endecasílabo heroico corto 0.9
Una barca se aleja lentamente, 11 [1, 3, 6, 8, 10] [1, 3, 6, 8, 10] Endecasílabo melódico pleno 1.0
una estela de luz, un vago canto, 11 [1, 3, 6, 7, 8, 10] [1, 3, 6, 8, 10] Endecasílabo melódico pleno 0.9
sombras que pasan sobre el quieto mar; 11 [1, 4, 8, 10] [1, 4, 8, 10] Endecasílabo sáfico puro pleno 1.0
Y las horas se van pasaudamente, 11 [3, 6, 8, 10] [3, 6, 8, 10] Endecasílabo melódico largo 1.0
mientras vierte la luz su último encanto 11 [3, 6, 7, 10] [3, 6, 10] Endecasílabo melódico puro 0.9
en un intenso pálido llamar 11 [2, 4, 6, 10] [2, 4, 6, 10] Endecasílabo heroico corto 1.0

<caption>**Figura 13.** Salida de Jumper obtenida con Python en un Notebook Jupyter</caption>

### 3.4.3. Escansión con código Python de un corpus de poemas

Usando la misma función, `jumper.escandir_texto()`, podemos aplicar Jumper sobre el texto de poemas contenidos en archivos diferentes, escribiendo los resultados por ejemplo en un único fichero delimitado, para facilitar el análisis de los datos con un programa de tipo hoja de cálculo. El código para
hacerlo se muestra no aquí sino en el notebook sobre Jumper en el repositorio GitHub del capítulo. La figura 14 muestra el resultado que se obtiene con ese código, abriendo el fichero de salida con LibreOffice Calc. Se ha usado el mismo corpus de poemas que se usó para Rantanplan en 3.3.2. En el archivo de salida se ha guardado un identificador para el poema (*numPoema*), el número de verso para cada verso, el número de sílabas métricas, la escansión, la escansión sin acentos antirríticos, el tipo métrico asignado y la tasa de coincidencia de los acentos métricos detectados con el tipo métrico. Es decir, se han reproducido la mayor parte de las columnas que se muestran en la interfaz gráfica de Jumper.

<table><caption>**Figura 14.** Salida de Jumper para un corpus de poemas obtenida con Python, guardada en formato delimitado y abierta con LibreOffice Calc</caption><thead><tr><th>A<br>numPoema</th><th>B<br>numVerso</th><th>C<br>verso</th><th>D<br>numSil</th><th>E<br>escansion</th><th>F<br>escansionSinAnt</th><th>G<br>tipoVerso</th><th>H<br>coincidencia</th></tr></thead><tbody><tr><td>1</td><td>1</td><td>1Enveluerto en sombras duerme en el misterio</td><td>11:2 4:10</td><td></td><td>2 4:10</td><td>Endecasilabo heroico corto</td><td>100</td></tr><tr><td>1</td><td>2</td><td>2de la noche plateada el olvidado</td><td>11:3 6:10</td><td></td><td>3 6:10</td><td>Endecasilabo méldico puro</td><td>100</td></tr><tr><td>1</td><td>3</td><td>3parque; glósa la brisa en el salterio</td><td>11:1 3:10</td><td></td><td>1 3:10</td><td>Endecasilabo méldico corto</td><td>100</td></tr><tr><td>1</td><td>4</td><td>4mágico del frondaje desmayado</td><td>11:1 6:10</td><td></td><td>1 6:10</td><td>Endecasilabo enfático puro</td><td>100</td></tr><tr><td>1</td><td>5</td><td>5leve cantata de sutil pesar.</td><td>11:1 4:10</td><td></td><td>1 4:10</td><td>Endecasilabo sáfico puro pleno</td><td>100</td></tr><tr><td>1</td><td>6</td><td>6Surca las ondas una azul estela</td><td>11:1 4:6 8:10</td><td></td><td>1 4:6 8:10</td><td>Endecasilabo sáfico puro</td><td>100</td></tr><tr><td>1</td><td>7</td><td>7que un barco deje sobre el glauso mar.</td><td>11:1 2:4 8:10</td><td></td><td>1 4:8 10</td><td>Endecasilabo sáfico puro pleno</td><td>90</td></tr><tr><td>1</td><td>8</td><td>8Un ave pia con fugaz cautela...</td><td>11:1 2:4 8:10</td><td></td><td>1 4:8 10</td><td>Endecasilabo sáfico puro pleno</td><td>90</td></tr><tr><td>1</td><td>9</td><td>9Es una queja el canto de la fuente</td><td>11:1 2:4 6:10</td><td></td><td>2 4:6 10</td><td>Endecasilabo heroico corto</td><td>90</td></tr><tr><td>1</td><td>10</td><td>10que va evocando mil recuerdos viejos,</td><td>11:2 4:6 8:10</td><td></td><td>2 4:6 8:10</td><td>Endecasilabo heroico pleno</td><td>100</td></tr><tr><td>1</td><td>11</td><td>11mientras sus aguas hacia el cielo miran.</td><td>11:4 8:10</td><td></td><td>4 8:10</td><td>Endecasilabo sáfico puro</td><td>100</td></tr><tr><td>1</td><td>12</td><td>12Y en un espasmo de ansiedad ardiente,</td><td>11:2 4:10</td><td></td><td>2 4:8 10</td><td>Endecasilabo sáfico largo pleno</td><td>100</td></tr><tr><td>1</td><td>13</td><td>13se alzran hasta los astras que allá lejan,</td><td>11:1 6:9 10</td><td></td><td>1 6:10</td><td>Endecasilabo enfático puro</td><td>90</td></tr><tr><td>1</td><td>14</td><td>14plenos de amor por su pasión suspiran.</td><td>11:1 4:8 10</td><td></td><td>1 4:8 10</td><td>Endecasilabo sáfico puro pleno</td><td>100</td></tr><tr><td>2</td><td>1</td><td>1 Rosas sangrantes sobre el mar desflora</td><td>11:1 4:8 10</td><td></td><td>1 4:8 10</td><td>Endecasilabo sáfico puro pleno</td><td>100</td></tr><tr><td>2</td><td>2</td><td>2el sol que dice adieses el tarde,</td><td>11:2 4:6 10</td><td></td><td>2 4:6 10</td><td>Endecasilabo heroico corto</td><td>100</td></tr><tr><td>2</td><td>3</td><td>3rían las aguas su canción sonora,</td><td>11:1 4:8 10</td><td></td><td>1 4:8 10</td><td>Endecasilabo sáfico puro pleno</td><td>100</td></tr><tr><td>2</td><td>4</td><td>4bajo nubes de fuego el poniente arde.</td><td>11:3 6:9 10</td><td></td><td>3 6:10</td><td>Endecasilabo méldico puro</td><td>90</td></tr><tr><td>2</td><td>5</td><td>5Vibran las cañas al chocar del viento,</td><td>11:1 4:8 10</td><td></td><td>1 4:8 10</td><td>Endecasilabo sáfico puro pleno</td><td>100</td></tr><tr><td>2</td><td>6</td><td>6formando extraña y triste sinfonia,</td><td>11:2 4:6 10</td><td></td><td>2 4:6 10</td><td>Endecasilabo heroico corto</td><td>100</td></tr><tr><td>2</td><td>7</td><td>7y la palmera altiva en valvén lento</td><td>11:4 6:10</td><td></td><td>4 6:10</td><td>Endecasilabo sáfico corto</td><td>90</td></tr></tbody></table>

# 4. ANÁLISIS AUTOMÁTICO DE OTRAS CARACTERÍSTICAS MÉTRICAS

## 4.1. Análisis automático de pausa y encabalgamiento

La existencia de verso presupone la de un discurso fragmentado por pausas. La crítica se ha interesado, aunque más como elemento estilístico que como métrico, por la coincidencia o no entre la pausa versal y la pausa de sentido.

Basándose en los experimentos de Quilis y su definición de encabalgamiento se crea la herramienta ANJA<fnref n="11" /> (Martínez Cantón, Ruiz Fabo, González-Blanco y Poibeau, 2017; Martínez Cantón y Ruiz Fabo, 2018; Ruiz Fabo, Martínez Cantón, Poibeau y González-Blanco, 2017), que analiza entre qué versos hay

<footnote n="11">11 El código está disponible en https://github.com/pruizf/anja, https://doi.org/10.5281/zenodo.10578321</footnote>
encabalgamiento y de qué tipo son<fnref n="12" />, sobre la base de anotaciones gramaticales obtenidas con la librería IXA Pipes (Agerri y Rigau, 2014). Esto permite saber, por inferencia, qué versos son esticomíticos. La herramienta se ha usado para anotar con encabalgamiento el corpus DISCO.

Para esta herramienta se creó un prototipo de interfaz. Esta permite el análisis de poemas sueltos simplemente pegando los versos en una ventana, como puede verse en la figura 15:

<figure><img src="image_15.png" /><figcaption>**Figura 15.** Captura de la herramienta ANJA</figcaption></figure>

La interfaz también permite el análisis de un corpus de varios poemas en texto plano cargando un zip con el corpus y enviándolo<fnref n="13" />. La herramienta

<footnote n="12">12 Aquí se recoge toda la información sobre este sistema y el acceso a su interfaz: https://sites.google.com/site/spanishenjambment/.</footnote>

<footnote n="13">13 En el servidor se ha limitado el número máximo de poemas a 50 (no es una limitación de la herramienta en sí, que en línea de comandos acepta un corpus de tamaño arbitrario, sino de los recursos del servidor de la interfaz).</footnote>
devuelve resultados en formato delimitado, indicando para cada poema los
pares de versos con encabalgamiento y su tipo.

## 4.2. Análisis automático de la rima

Existen herramientas capaces de detectar y clasificar la rima, tarea sencilla para la rima consonante y que, quizás por este motivo, no ha recibido mucha atención. La tarea en español, sin embargo, es algo más compleja, ya que las particularidades de la rima asonante la complican. En inglés tampoco es una tarea sencilla. No obstante, se ha trabajado en modelos para diferentes lenguas. Con muy buenos resultados encontramos la herramienta RhymeTagger (Plecháč, 2018), que exige, asimismo, el uso de línea de comandos. Este sistema se basa en un algoritmo que aprende automáticamente (sobre una base estadística) a partir de pares de rimas comunes en un corpus, pudiendo usar como entrada la representación ortográfica del texto o una transcripción fonética. Es decir, no funciona por reglas, sino que aprende a determinar si dos palabras riman a partir de las rimas disponibles en un corpus. Su algoritmo, en lugar de buscar coincidencias precisas de sonidos, trabaja con las probabilidades de que dos palabras riman juntas derivadas de los propios textos analizados. Esto es lo que le permite funcionar para distintas lenguas, sin aplicar un análisis lingüístico específico a cada una de ellas. El método se ha probado en corpus de poesía en siete lenguas diferentes, entre ellos el checo, español, inglés, francés y alemán. Veremos cómo usar la herramienta en la sección 3.3.2.

Para textos en español, Rantanplan también permite anotar rimas, con un método a base de reglas. Como salida, ofrece el esquema rimático (p. ej. *abab*), la rima en sí (la parte de la palabra final que rima) y una indicación sobre el tipo de rima (consonante o asonante). Veremos cómo usar la herramienta en la sección 5.1.

Para el etiquetado de rima en el corpus DISCO, usamos RhymeTagger (el modelo español de RhymeTagger se obtuvo a partir de ese esequipo además del corpus de Navarro-Colorado et al., 2016). Los resultados de anotación automática de rima han sido útiles para obtener datos cuantitativos sobre la distribución de esquemas rimáticos (Ruiz Fabo et al., 2021, p. i73). La aplicación de la anotación automática también fue útil en el trabajo editorial sobre el corpus, para detectar problemas textuales. Se observaron casos en que RhymeTagger no detecta una rima, no porque esta no exista, sino porque había un error en la fuente que imposibilitaba su detección (p. ej. *corales* transcrito como *colores*, con lo que la herramienta no detecta su rima con *maternales*).
# 5. EJERCICIO PRÁCTICO DE ANOTACIÓN DE RIMA

## 5.1. Anotación de rima con Rantanplan

Proponemos la utilización de las herramientas Rantanplan y RhymeTagger para la anotación de la rima.

La herramienta Rantanplan ya he visto en el ejercicio 3.3, sobre sus funciones de escansión automática. Usamos aquí la función de análisis de rima. La instalación de Rantanplan y de sus dependencias se ha explicado en 3.3. Damos aquí un ejemplo básico de anotación de rimas. Un notebook<fnref n="14" /> con explicaciones adicionales está disponible en el repositorio del capítulo.

Asumiendo que el texto del poema está asignado a un variable `texto-poema`, como se vio para la escansión, el código en (14) proporciona las informaciones de rima:

(14)
```

    resultado = get_scansion(texto-poema, rhyme_analysis= True)
    for verso in resultado:
        try:
            identificador_rima = verso["rhyme"]
            rima = verso["ending"]
            tipo_rima = verso["rhyme_type"]
            # para sacar la palabra rima
            versoSinPuntuacion = [token for token in verso["tokens"]
                                 if "word" in token]
            palabra_rima = "".join([silaba["syllable"] for silaba
                                     in versoSinPuntuacion[-1]
                                     ["word"]])
            # mostrar los resultados
            print(f"{identificador_rima}\t{rima}\t" +
                   f"{palabra_rima}\t {tipo_rima}")
        except Exception as e:
            print(f"Error: {e}")
```

<footnote n="14">14 https://github.com/HD-aula-Literatura/III-8-Verso/blob/main/etiquetado-rima-ran tanplan.ipynb.</footnote>
La salida para el código en (14) se ve en (15). Aparte de esta salida básica, el notebook describe cómo formatear la salida de maneras diferentes (p. ej. para añadir el número de verso o mostrar el texto de cada verso).

(15)
a ora desflora consonant
b arde tarde consonant
a ora sonora consonant
b arde arde consonant
c ento viento consonant
d ia sinfonía consonant
c ento lento consonant
d ia armonía consonant
e ente lentamente consonant
f anto canto consonant
g ar mar consonant
e ente pausadamente consonant
f anto encanto consonant
g ar llamear consonant

La diferencia con respecto al código para escansión es que para obtener la información de rima debemos añadir la opción `rhyme_analysis=True` al aplicar la función `get_scansion()`. Esto va a añadir claves relacionadas con la rima al diccionario de datos devuelto por Rantanplan para cada verso. El código de (14) aprovecha estas claves para mostrar la información de rima, concretamente:

* `rhyme`: Posición del verso dentro del esquema rimático, expresada con una letra minúscula. P. ej. la primera posición se expresa como `a`, la segunda como `b` etc. Para un serventesio, como el del ejemplo, esto daría el esquema `abab`; en la aplicación el esquema rimático de los versos de arte mayor también se expresa con letras minúsculas.

* `ending`: Secuencia ortográfica que expresa la rima.

* `rhyme_type`: Consonante o asonante

La palabra rima no está directamente disponible en los resultados de Rantanplan, pero se puede obtener a partir de estos. El código para hacerlo se ve en (14) y se explica en el repositorio.

## 5.2. Anotación de rima con RhymeTagger

RhymeTagger tiene un uso sencillo y dos ventajas con respecto a Rantanplan: En primer lugar, es multilingüe. En segundo lugar, no requiere una librería de
análisis lingüístico como spaCy. Por el contrario, la salida es más sencilla que la de Rantanplan: RhymeTagger da el esquema rimático pero no las rimas en sí (no las secuencias que constituyen la rima). Explicamos en detalle su funcionamiento en un notebook<fnref n="15" />, tanto para etiquetar un poema como un corpus completo. Reproducimos aquí el código básico para usarlo y la salida obtenida; las explicaciones están en el notebook.

Después de instalar la librería con `!pip install rhymetagger` (desde un notebook Jupyter), podemos aplicarla con el código en (16), que asume que el texto del poema ya ha sido asignado como cadena de texto a una variable llamada `texto-poema`, como en los ejemplos anteriores del capítulo. El código se explica en el repositorio, pero el ejemplo (16) muestra que con poco código se pueden obtener resultados con esta herramienta. La salida se da en (17).

```python
(16) from rhymetagger import RhymeTagger
from string import ascii_lowercase

rt = RhymeTagger()
rt.load_model(model='es')

texto-poema_lista = [linea for linea in texto-poema.split("\n")
                      if linea != ""]

rimas = rt.tag(texto-poema_lista, output_format=3)

rimas_letras = [ascii_lowercase[posicion_esquema-1]
                 if posicion_esquema is not None
                 else "-" for posicion_esquema in rimas]

for indice, verso in enumerate(texto-poema_lista):
    print(f"{indice+1}\t{verso:<40}\t" +
          f"{rimas_letras[index]}")
```

<footnote n="15">15 https://github.com/HD-aula-Literatura/III-8-Verso/blob/main/etiquetado-rima-rhymetagger.ipynb.</footnote>
(17)
1 Rosas sangrantes sobre el mar desflora a
2 el sol que dice adioses en la tarde, b
3 riman las aguas su canción sonora, a
4 bajo nubes de fuego el poniente arde. b
5 Vibran las cañas al chocar del viento, c
6 formando extraña y triste sinfonía, d
7 y la palmera altiva en vaivén lento c
8 es una glauca nota de armonía. d
9 Una barca se aleja lentamente, e
10 una estela de luz, un vago canto, f
11 sombras que pasan sobre el quieto mar; g
12 Y las horas se van pausadamente, e
13 mientras vierte la luz su último encanto f
14 en un intenso, pálido llamear. g

## 6. ÚLTIMAS REFLEXIONES

Toda herramienta se basa en unos presupuestos teóricos que determinarán sus resultados. El uso de estos programas puede, además, hacernos cuestionar la teoría métrica que queremos utilizar en nuestro corpus. Así, el camino entre el análisis automático y la métrica teórica es de ida y vuelta, ya que suponen una formalización y una puesta en práctica de la teoría a gran escala, lo que puede implicar un replanteamiento de ciertas categorías.

Además, el análisis automático del verso sirve, en muchas ocasiones, como procedimiento de preparación y corrección del corpus (si encontramos incon- sistencias métricas), o incluso para detectar errores en la transmisión de un poema.

En todo caso, de manera general, el análisis métrico automático por medio de estas herramientas nos da acceso en el análisis literario de un autor, época, escuela, etc., a una información muy valiosa que antes era prácticamente inaprensible.

Es posible que dentro de un tiempo contemos con interfaces gráficas sen- cillas que permitan utilizar este tipo de programas sin tener ningún conoci- miento de programación. Mientras esto sucede conviene saber implementar las instrucciones de uso de este tipo de programas con código y línea de comandos. Ello nos abrirá el camino a otros muchos programas que nos interesen.
REFERENCIAS BIBLIOGRÁFICAS

Agerri, R., y Rigau, G. (2014). IXA pipeline: Efficient and Ready to Use Multilingual NLP tools. LREC 2014. Language Resources and Evaluation Conference, 3823-3828

Agirrezabal, M., Alegria, I., y Hulden, M. (2017). A Comparison of Feature-Based and Neural Scansion of Poetry. *RANLP 2017 - Recent Advances in Natural Language Processing Meet Deep Learning*, 18-23. https://doi.org/10.26615/978-954-452-049-6_003

Bermúdez Sabel, H. (2019). As humanidades dixitais e a súa aplicación á varianción lingüística na lírica galego-portuguesa. Tesis doctoral, Universidade de Santiago de Compostela. https://dialnet.unirioja.es/servlet/tesis?codego=221036

Bories, A. S., Ruiz Fabo, P., y Plecháč, P. (2022). The Polite Revolution of Computational Literary Studies. Computational Stylistics in Poetry, Prose, and Drama, 1-18.

De la Rosa, J., Pérez, Á., Hernández, L., Ros, S., y González-Blanco, E. (2020). Rantanplan, fast and accurate syllabification and scansion of spanish poetry. *Procesamiento Del Lenguaje Natural*, (65), 83-90.

Domínguez Caparrós, J. (1990). Métrica y poética en Rubén Darío. In T. Albaladejo, F. J. Blasco Pascual, y R. de la Fuente Ballesteros, *El modernismo: La renovación de los lenguajes poéticos* (pp. 31-46). Universidad de Valladolid. Retrieved from https://dialnet.unirioja.es/servlet/articulo?codego=553672

Domínguez Caparrós, J. (2002). *Métrica de Cervantes*. Centro Estudios Cervantinos.

Gervás, P. (2000). A Logic Programming Application for the Analysis of Spanish Verse. In J. Lloyd, V. Dahl, U. Furbach, M. Kerber, K.-K. Lau, C. Palamidessi, ... P. J. Stuckey (Eds.), *Computational Logic-CL 2000* (pp. 1330-1344). Springer. https://doi.org/10.1007/3-540-44957-4_89

Gómez Bravo, A. M. (1998). *Repertorio métrico de la poesía cancioneril del siglo XV*. Universidad de Alcalá. Retrieved from https://dialnet.unirioja.es/servlet/libro?codego=195165

Honnibal, M., Montani, I., Van Landeghem, S., y Boyd, A. (2020). spaCy: Industrial-strength Natural Language Processing in Python. 10.5281/zenodo.1212303

Hrushovski, B. (1960). On free rhythms in modern poetry. En T. A. Sebeok (Ed.), *Style in language* (pp. 173-190).

Jakobson, R. (1975). *Ensayos de lingüística general*. Seix Barral.

Jauralde Pou, P. (2020). *Métrica española*. Cátedra.
Logan, H. M. (1988). Computer Analysis of Sound and Meter in Poetry. *College Literature*, 15(1), 19-24.

Marco, G., De La Rosa, J., Gonzalo, J., Ros, S., y González-Blanco, E. (2021). Automated Metric Analysis of Spanish Poetry: Two Complementary Approaches. *IEEE Access*, (9), 51734-51746. https://doi.org/10.1109/ACC.ESS.2021.3069635

Marco, G., y Gonzalo, J. (2021). Escansión automática de poesía española sin silabación. *Procesamiento del lenguaje natural*, (66), 77-87.

Martínez Cantón, C., Ruiz Fabo, P., González-Blanco, E., y Poibeau, T. (2017, October). *Automatic Enjambment Detection as a New Source of Evidence in Spanish Versification*. Presented at the Plotting Poetry / Machiner la poésie, Basel. Retrieved from https://zenodo.org/record/1006765

Martínez Cantón, Clara I., y Ruiz Fabo, P. (2018). *ANJA, ¿dónde están los enca-balgamientos?* Presented at the DH-2018, Ciudad de México, México.

Martínez Cantón, Clara Isabel. (2011). *Métrica y poética de Antonio Colinas*. Padilla Libros Editores & Libreros.

Navarro-Colorado, B., Ribes Lafoz, M., y Sánchez, N. (2016). Metrical anno-tation of a large corpus of Spanish sonnets: Representation, scansion and evaluation. *Proceedings of the Tenth International Conference on Language Resources and Evaluation (LREC’16)*, 4360-4364. https://aclanthology.org/L16-1691/

Navarro-Colorado, B. (2017). A metrical scansion system for fixed-metre Spa-nish poetry. *Digital Scholarship in the Humanities*. https://doi.org/10.1093/llc/fqx009

Newman, M. (1986). Poetry processing. *Byte Mag*, 11(2), 224-225.

Plecháč, P. (2018). A Collocation-Driven Method of Discovering Rhymes (in Czech, English, and French Poetry). En M. Fidler y V. Cvrček (Eds.), *Taming the Corpus: From Inflection and Lexis to Interpretation* (pp. 79-95). Springer International Publishing. https://doi.org/10.1007/978-3-319-98017-1_5

Plecháč, P. (2021). *Versification and Authorship Attribution*. Charles University in Prague, Karolinum Press.

Plecháč, P., Scherr, B. P., Skulacheva, T., Bermúdez-Sabel, H., y Kolár, R. (2019). *Quantitative Approaches to Versification*. Institute of Czech Literature of the Czech Academy of Sciences.

Ruiz Fabo, P., Martínez Cantón, C., Poibeau, T., y González-Blanco, E. (2017). Enjambment Detection in a Large Diachronic Corpus of Spanish Sonnets. *Proceedings of the Joint SIGHUM Workshop on Computational Linguistics for Cultural Heritage, Social Sciences, Humanities and Literature*, 27-32. Retrieved from http://www.aclweb.org/anthology/W17-2204