library(xml2)
library(dplyr)
library(purrr)
library(tidyr)
library(stringr)
library(tibble)
library(ggraph)
library(igraph)
library(ggplot2)
library(syuzhet)Анализ Священного писания
Библиотеки
В данном проекте проводится компьютерный анализ библейского текста в испанском переводе, размеченного в формате XML-TEI. Особенность используемого корпуса заключается в детальной разметке прямой речи, включая указание говорящего, адресата и типа коммуникации. Это позволяет рассмотреть текст не только как последовательность слов, но и как структуру речевых актов.
Текстовые данные взяты из проекта XML-TEI Bible (José Calvo Tello), свободно доступного на GitHub.
В первую очередь, загрузим необходимые библиотеки для работы.
bible_xml <- read_xml("TEIBible.xml")
ns <- xml_ns(bible_xml)В качестве минимальной единицы анализа были выбраны стих (<ab type="verse">), так как он представляет собой устойчивую смысловую и структурную единицу библейского текста, а также сегменты прямой речи (<q>) для сохранения связи между уровнем текста и уровнем коммуникации.
На уровне стихов формируем базовый корпус, включающий идентификаторы книги и главы, а также приблизительную длину текста в словах. Эти данные нам нужны в основном для ориентации в самом корпусе.
verses <- xml_find_all(bible_xml, ".//d1:ab[@type='verse']", ns = ns)
verses_tbl <- tibble(
verse_id = xml_attr(verses, "id"),
verse_n = xml_attr(verses, "n"),
text_raw = xml_text(verses)
) %>%
mutate(
chapter_id = str_remove(verse_id, "\\.\\d{3}$"),
book = str_extract(verse_id, "(?<=b\\.)[A-Z]+"),
verse_length = str_count(text_raw, "\\b\\w+\\b")
) %>%
relocate(book, chapter_id, .before = verse_id)Для каждого сегмента прямой речи сохраняется информация о говорящем, адресате и объёме текста. Связь сегмента с конкретным стихом восстанавливается через иерархию XML-документа (книга -> глава -> стих).
speech <- xml_find_all(bible_xml, ".//d1:q", ns = ns)
speech_tbl <- tibble(
speech_text = xml_text(speech),
who = xml_attr(speech, "who"),
to_whom = xml_attr(speech, "toWhom"),
type = xml_attr(speech, "type")
) %>%
mutate(
verse_id = map_chr(speech, ~ xml_attr(xml_find_first(.x, "ancestor::d1:ab", ns = ns), "id")),
book = str_extract(verse_id, "(?<=b\\.)[A-Z]+"),
chapter_id = str_remove(verse_id, "\\.\\d{3}$"),
speech_length = str_count(speech_text, "\\b\\w+\\b")
) %>%
relocate(book, chapter_id, .before = verse_id) Попытка измерять долю прямой речи через отношение количества слов прямой речи к общему объёму текста приводит к проблеме двойного учёта, связанной с сегментацией речи внутри стихов. В связи с этим в анализе были использованы показатели интенсивности прямой речи: количество речевых сегментов и суммарный объём речи, нормализованные на число глав.
chapter_stats <- speech_tbl %>%
group_by(book, chapter_id) %>%
summarise(
speech_words = sum(speech_length),
speech_segments = n(),
.groups = "drop"
)
book_stats <- chapter_stats %>%
group_by(book) %>%
summarise(
total_speech_words = sum(speech_words),
total_segments = sum(speech_segments),
chapters = n(),
segments_per_chapter = total_segments / chapters,
speech_words_per_chapter = total_speech_words / chapters,
.groups = "drop"
) %>%
filter(!is.na(book))Полученные данные позволяют сравнивать коммуникативную структуру различных частей Библии.
ggplot(book_stats,
aes(x = reorder(book, segments_per_chapter),
y = segments_per_chapter)) +
geom_col(fill = "firebrick") +
coord_flip() +
labs(
title = "Интенсивность прямой речи по книгам Библии",
x = "Книга",
y = "Среднее число речевых сегментов на главу"
) +
theme_minimal()ggplot(book_stats,
aes(x = segments_per_chapter,
y = speech_words_per_chapter,
label = book)) +
geom_point() +
geom_text(check_overlap = TRUE, size = 3) +
labs(
title = "Структура прямой речи в книгах Библии",
x = "Речевых сегментов на главу",
y = "Слов прямой речи на главу"
) +
theme_minimal()Диаграмма интенсивности прямой речи показывает, что наибольшее среднее число речевых сегментов на главу наблюдается в книге JOE (Книга пророка Иоиля). Это связано с жанровой спецификой текста: книга построена преимущественно как последовательность пророческих высказываний и обращений, в которых прямая речь играет центральную структурную роль. В отличие от повествовательных книг, где речь встроена в нарратив, в пророческих текстах именно речевые акты формируют основной объём содержания.
Дополнительно была предпринята попытка рассмотреть структуру коммуникации как сеть взаимодействий между говорящими и адресатами. Узлы сети представляют персонажей, а рёбра — акты прямой речи, взвешенные по объёму текста.
edges <- speech_tbl %>%
filter(book == "GEN" & !is.na(to_whom)) %>%
separate_rows(to_whom, sep = " ") %>%
group_by(who, to_whom) %>%
summarise(weight = sum(speech_length), .groups = "drop")
graph_full <- graph_from_data_frame(edges, directed = TRUE)
node_strength <- tibble(
node = names(strength(graph_full, mode = "all")),
strength = strength(graph_full, mode = "all")
)
top_nodes <- node_strength %>%
arrange(desc(strength)) %>%
slice_head(n = 15) %>%
pull(node)
edges_top <- edges %>%
filter(who %in% top_nodes & to_whom %in% top_nodes)graph <- graph_from_data_frame(edges_top, directed = TRUE)
ggraph(graph, layout = "fr") +
geom_edge_link(aes(width = weight), alpha = 0.5, color = "lightgreen") +
geom_node_point(size = 5, color = "darkblue") +
geom_node_text(aes(label = name), repel = TRUE) +
labs(title = "Сетевой граф прямой речи в Библии") +
theme_void()Сетевой граф, построенный на основе прямой речи в книге Бытия, демонстрирует выраженную асимметрию коммуникативной структуры. Наибольшее количество связей и наибольшую суммарную «силу» узлов имеют персонажи с идентификаторами per14 и per4. Это указывает на их центральную роль в коммуникативной сети текста, где они выступают основными источниками и адресатами речевых актов.
genesis_speech <- speech_tbl %>%
filter(book == "GEN", !is.na(speech_text) & speech_text != "") %>%
select(who, speech_text)
sentiment_score <- get_nrc_sentiment(genesis_speech$speech_text, language = "spanish")
genesis_sentiment <- bind_cols(genesis_speech, sentiment_score)
sent_by_who <- genesis_sentiment %>%
group_by(who) %>%
summarise(
positive = sum(positive),
negative = sum(negative),
net_sentiment = positive - negative,
.groups = "drop"
) %>%
arrange(desc(abs(net_sentiment)))sent_by_who %>%
slice_head(n = 10) %>%
ggplot(aes(x = reorder(who, net_sentiment), y = net_sentiment, fill = net_sentiment > 0)) +
geom_col() +
coord_flip() +
scale_fill_manual(values = c("TRUE" = "forestgreen", "FALSE" = "firebrick")) +
labs(
title = "Сентимент-анализ прямой речи персонажей Бытия (syuzhet NRC, испанский)",
x = "Персонаж",
y = "Net-сентимент (положит. − отрицат.)"
) +
theme_minimal()speech_nonempty <- speech_tbl %>%
filter(!is.na(speech_text) & speech_text != "")
sentiment_scores <- get_nrc_sentiment(speech_nonempty$speech_text, language = "spanish")
speech_sentiment <- bind_cols(
speech_nonempty %>% select(book, speech_text),
sentiment_scores
)
sent_by_book <- speech_sentiment %>%
filter(!is.na(book)) %>%
group_by(book) %>%
summarise(
positive = sum(positive),
negative = sum(negative),
net_sentiment = positive - negative,
.groups = "drop"
) %>%
arrange(desc(net_sentiment))top_books <- sent_by_book %>% slice_head(n = 10)
ggplot(top_books, aes(x = reorder(book, net_sentiment), y = net_sentiment, fill = net_sentiment > 0)) +
geom_col() +
coord_flip() +
scale_fill_manual(values = c("TRUE" = "forestgreen", "FALSE" = "firebrick")) +
labs(
title = "Net-сентимент прямой речи по книгам Библии (syuzhet NRC, испанский)",
x = "Книга",
y = "Net-сентимент (положит. − отрицат.)"
) +
theme_minimal()Результаты сентимент-анализа прямой речи показывают, что наибольшее положительное значение суммарного net-сентимента наблюдается в книге Псалтырь. Это согласуется с поэтическим и молитвенным характером текста, в котором преобладает лексика, связанная с выражением благодарности, радости и упования.
Подведем итоги! Проведённый анализ показал, что TEI-разметка позволяет исследовать библейский текст на уровне структуры коммуникации. Использование количественных показателей прямой речи выявляет различия между книгами и главами, не затрагивая содержательных или богословских интерпретаций текста.