Перейти к содержанию

Стиховедческие статистики

VerseStats(source, stress_dict=None)

Стиховедческие статистики текста: ударения, метр и стопы, рифмовка, окончания строк и строфы. Источник данных - текст с переносами строк или объект Doc библиотеки spaCy.

Строфы разделяются пустыми строками. Ударения ставятся по словарю StressDict и подгоняются под метр (алгоритм). Знак ударения в тексте важнее словаря и на икт не переносится, поэтому текст после функции accentuate, где ударения расставлены без метра, дает другие значения, чем тот же текст без знаков; ударная по знаку проклитика забирает ударение слова за ней через пробел (на́ сердце). Сами знаки и мягкие переносы в строки не попадают.

Словарь ударений загружается один раз: StressDict().download() (10 МБ). Текст с буквами, но без русских слов (латиница) дает пустые статистики - n_lines 0, метр None, доли nan.

Исключения:

  • SourceTypeError - источник, который не строка и не Doc, словарь ударений другого типа;
  • SourceError - источник без слов (пустой, из цифр и знаков);
  • DatasetNotFoundError - словарь ударений не загружен.
from ruts import VerseStats
from ruts.datasets import StressDict

StressDict().download()
text = """Мой дядя самых честных правил,
Когда не в шутку занемог,
Он уважать себя заставил
И лучше выдумать не мог."""
vs = VerseStats(text)
vs.print_stats()
            Статистика             | Значение
----------------------------------------------
Количество строк                   |    4
Количество строф                   |    1
Метр                               |   ямб
Число стоп                         |    4
Доля отклонений от метра           |   0.00
Доля пропущенных ударений на иктах |   0.19
Доля рифмованных строк             |   1.00
Доля мужских окончаний             |   0.50
Доля женских окончаний             |   0.50
Доля дактилических окончаний       |   0.00

Параметры

Параметр Тип По умолчанию Описание
source str / Doc - Источник данных
stress_dict StressDict None Словарь ударений; по умолчанию StressDict()

Атрибуты

Атрибут Тип Описание
stress_dict StressDict Словарь ударений
lines tuple[str] Строки с русскими словами
stanzas tuple[tuple[str, ...], ...] Строки по строфам
mean_line_len float Средняя длина строки в слогах
stresses tuple[tuple[int, ...], ...] Номера ударных слогов каждой строки, считая с нуля
patterns tuple[str, ...] Схемы строк из символов c (безударный слог) и C (ударный)
c_stressed_vowels dict[str, int] Распределение ударных гласных
vs.patterns
vs.stresses[1]
vs.c_stressed_vowels
('cCcCcCcCc', 'cCcCcccC', 'cccCcCcCc', 'cCcCcccC')
(1, 3, 7)
{'а': 5, 'я': 2, 'у': 2, 'о': 2, 'е': 1, 'ы': 1}

Метрики

Каждая метрика - атрибут объекта, вычисленный при его создании, а get_stats дает их все.

Метрика Что измеряет Диапазон Чем больше, тем
n_lines, n_stanzas Количество строк со словами и строф от 0 длиннее текст
meter Силлабо-тонический метр ямб, хорей, дактиль, амфибрахий, анапест, None без метра -
n_feet Преобладающее число стоп в строке от 1, None без метра длиннее строки
p_deviations Доля ударений многосложных слов на слабых позициях 0-0.1, nan без метра дальше ударения от метра
p_pyrrhics Доля иктов без ударения 0-1, nan без метра больше пропущенных ударений
p_rhymed Доля рифмованных строк 0-1, nan без строк больше рифм
p_masculine, p_feminine, p_dactylic Доли мужских, женских и дактилических окончаний 0-1, nan без окончаний больше таких окончаний

Метр и стопы

meter · n_feet · c_feet · p_deviations · Барахнин и др., 2019

detect_meter(text, stress_dict=None)

Метр стихотворения по алгоритму: ямб, хорей, дактиль, амфибрахий, анапест или None, если силлабо-тонический метр не подобран, - так отсеиваются дольник, акцентный стих, силлабика, верлибр и проза. Число стоп строки - число ее иктов, c_feet - распределение строк по числу стоп, p_deviations считается после подгонки ударений под метр.

Параметр Тип По умолчанию Описание
text str - Текст стихотворения
stress_dict StressDict None Словарь ударений; по умолчанию StressDict()

Исключения - те же, что у VerseStats.

from ruts.verse_stats import detect_meter

lermontov = """Тучки небесные, вечные странники!
Степью лазурною, цепью жемчужною
Мчитесь вы, будто как я же, изгнанники,
С милого севера в сторону южную.

Кто же вас гонит: судьбы ли решение?
Зависть ли тайная? злоба ль открытая?
Или на вас тяготит преступление?
Или друзей клевета ядовитая?"""

blok = """Девушка пела в церковном хоре
О всех усталых в чужом краю,
О всех кораблях, ушедших в море,
О всех, забывших радость свою."""

detect_meter(lermontov), detect_meter(blok)
vs.c_feet
('дактиль', None)
{4: 4}

Пиррихии и профиль ударности

p_pyrrhics · stress_profile

Доля иктов без ударения (пиррихиев в двусложных метрах) среди всех иктов строк; stress_profile - доля ударных иктов по позициям в строке, от первого икта к последнему. Без метра p_pyrrhics равна nan, а профиль пуст.

\[ \frac{\textrm{Количество иктов без ударения}}{\textrm{Количество иктов}} \]
vs.p_pyrrhics, vs.stress_profile
(0.1875, (0.75, 1.0, 0.5, 1.0))

Рифма

p_rhymed · rhyme_schemes · RIFMA

rhyme_scheme(text, stress_dict=None)

Схема рифмовки стихотворения: схемы строф через пробел, нерифмованные строки обозначены дефисом (ABAB, -A-A, AABB CC). У объекта схемы по строфам - в rhyme_schemes.

Параметр Тип По умолчанию Описание
text str - Текст стихотворения
stress_dict StressDict None Словарь ударений; по умолчанию StressDict()

Исключения - те же, что у VerseStats.

from ruts.verse_stats import rhyme_scheme

rhyme_scheme(lermontov), rhyme_scheme(blok)
vs.rhyme_schemes, vs.p_rhymed
('ABAB ABAB', 'ABAB')
(('ABAB',), 1.0)

Окончания строк

p_masculine · p_feminine · p_dactylic · c_clausulas

Тип окончания (клаузулы) строки - по числу слогов после последнего ударения: мужское - ударение на последнем слоге, женское - один заударный слог, дактилическое - два, гипердактилическое - три и больше (VERSE_CLAUSULAS, как у stress_type слова). c_clausulas - распределение строк по типам; доли считаются от строк с известным ударением последнего слова.

vs.c_clausulas
{'мужская': 2, 'женская': 2}

Методы

accentuate() возвращает текст со знаком акута (U+0301) после ударных гласных, с ударениями, подогнанными под метр; безударные слова (клитики, односложные вне икта) и слова без найденного ударения остаются без знака. В текст попадают только строки со словами, строфы разделяются пустой строкой.

print(vs.accentuate())
Мой дя́дя са́мых че́стных пра́вил,
Когда́ не в шу́тку занемо́г,
Он уважа́ть себя́ заста́вил
И лу́чше вы́думать не мо́г.

Остальные методы - get_stats, to_dataframe, print_stats и describe - из интерфейса статистик ядра anyTS; шкал у стиховедческих статистик нет, и describe возвращает для них None.

vs.get_stats()
{'n_lines': 4,
 'n_stanzas': 1,
 'meter': 'ямб',
 'n_feet': 4,
 'p_deviations': 0.0,
 'p_pyrrhics': 0.1875,
 'p_rhymed': 1.0,
 'p_masculine': 0.5,
 'p_feminine': 0.5,
 'p_dactylic': 0.0}

Алгоритм

Ударения и метр определяются по алгоритму Барахнина, Кожемякиной и Кузнецовой (CEUR 2019):

  1. Ударения по словарю. Ударный слог слова - по букве ё, у односложного слова единственный, иначе по словарю StressDict с поправками STRESS_CORRECTIONS (ошибочные и подвижные ударения словаря: себе́, зо́лото). Составное слово через дефис ищется целиком, затем по частям, поэтические стяжения (желанье - желание) и деепричастия (забыв - забывший) - по полной форме.
  2. Подбор метра. Сильные позиции (икты) пяти метров: ямб cC, хорей Cc, дактиль Ccc, амфибрахий cCc, анапест ccC (VERSE_METERS). Выбирается метр, при котором меньше всего словарных ударений многосложных слов попадает на слабые позиции, при равенстве - с наибольшим числом ударных иктов. Ударение в анакрузе - на слогах до первого икта строки - нарушением не считается (Ста́ли дни холоднее).
  3. Снятие неоднозначности. Односложные предлоги, союзы и частицы (VERSE_PROCLITICS) безударны, остальные односложные слова ударны только на икте, многосложные служебные слова (VERSE_WEAK_WORDS: или, чтобы) - если словарное ударение попадает на икт. Словарное ударение многосложного слова на слабой позиции переносится на икт, если в слове ровно один икт, такое слово в строке одно или все они двусложные (подвижное ударение: воды́ - во́ды) и после переноса в строке не остается нарушений; ударение по букве ё и в анакрузе не переносится. Слово без словарного ударения получает единственный икт, при нескольких иктах ударение последнего слова строки выбирается по рифме с соседними, иначе - последний икт.
  4. Проверка. Метр не определен, если после подгонки на слабых позициях остается больше десятой части ударений многосложных слов (VERSE_MAX_DEVIATIONS) или на икт перенесено больше 15% их словарных ударений (VERSE_MAX_MOVED) при четырех и более переносах (VERSE_MIN_MOVED); ударения тогда ставятся по словарю. Метр не подбирается и при словарных ударениях многосложных слов меньше шести (VERSE_MIN_STRESSES).

Рифма ищется в окне RHYME_WINDOW (4) строк внутри строфы по фонетическому ключу окончания - хвоста строки от последнего ударного слова: ударная гласная (я/а, ё/о, ю/у, ы/и сведены, е рифмуется и с о), группа согласных после нее по произношению (с оглушением и упрощением сочетаний: стн - сн) и число заударных слогов. Опорный согласный открытых мужских окончаний и заударные гласные не сравниваются, поэтому находятся и точные, и приблизительные рифмы (пламя - память, лето - одетой); окончания с разной группой согласных (ветер - вечер) не рифмуются. Буквы схемы рифмовки идут по порядку появления: прописные, затем строчные.

Точность проверена на наборе RIFMA (5121 строфа с ручной разметкой ударений и рифм, MIT): ударения совпадают с разметкой у 97% слов (у слов вне словаря - 71%), пары рифмующихся строк находятся с точностью 94% и полнотой 90%, схема строфы целиком совпадает в 78% случаев; метр не определен у 8% строф, в том числе у 3% - из-за порога VERSE_MIN_STRESSES. Часть поправок STRESS_CORRECTIONS собрана по этой же разметке, так что оценка ударений отчасти внутривыборочная: поправки, собранные по одной половине набора, добавляют на другой 0.1-0.2 процентного пункта.

Расстановка ударений

accentuate(text, stress_dict=None)

Расстановка знаков акута (U+0301) после ударных гласных текста по словарю, без учета метра (под метр ударения подгоняет метод VerseStats.accentuate); уже стоящий в тексте знак ударения сохраняется, а односложные предлоги, союзы и частицы и слова без найденного ударения остаются без знака.

Параметр Тип По умолчанию Описание
text str - Текст
stress_dict StressDict None Словарь ударений; по умолчанию StressDict()

Исключения:

  • SourceTypeError - текст, который не строка, словарь ударений другого типа;
  • DatasetNotFoundError - словарь ударений не загружен.
from ruts.verse_stats import accentuate

accentuate("Уже поздно, замерли на полночь.")
'Уже́ по́здно, за́мерли на по́лночь.'

Строфы

split_stanzas(text)

Деление текста на строфы и строки: строфы разделяются пустыми строками, строки без русских слов (номера, звездочки) пропускаются.

Параметр Тип По умолчанию Описание
text str - Текст стихотворения

Исключения:

  • SourceTypeError - текст, который не строка.
from ruts.verse_stats import split_stanzas

split_stanzas(
    "Буря мглою небо кроет,\nВихри снежные крутя;\n\n* * *\n\nТо, как зверь, она завоет,"
)
[['Буря мглою небо кроет,', 'Вихри снежные крутя;'],
 ['То, как зверь, она завоет,']]