Анализ журнала stephanos

Анализ названий статей в журнале stephanos

Автор

Карина Чадаева

Дата публикации

01.12.2024

Подготовка данных

Подгружаю необходимые библиотеки

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(rvest)

Attaching package: 'rvest'

The following object is masked from 'package:readr':

    guess_encoding

Создаю tibble

url <- "https://www.stephanos.ru/index.php?lp=41"
html <- read_html(url)

# Получаю ссылки на статьи
toc <- html |> 
  html_elements(".papTitle a:nth-child(1)")

urls <- tibble(
  href = toc |> 
    html_attr("href")
) |> 
  mutate(link = paste0("https://www.stephanos.ru/", href)) |> 
  pull(link)


# Функции для извлечения выпусков и работ
get_works <- function(url) {
  read_html(url) |> 
    html_elements(".papTitle") |> 
    html_text2()
}

get_issues <- function(url) {
  read_html(url) |> 
    html_elements(".numTitle") |> 
    html_text2()
}

all_works <- map(urls, get_works)
all_issues <- map(urls, get_issues)

my_tbl <- tibble(
  issue = rep(unlist(all_issues), lengths(all_works)),
  work = unlist(all_works)
)

final_tibble <- my_tbl |> 
  separate(issue, into = c("year", "number_this_year", "number_total"), 
           sep = " \\№ | \\(|\\)", convert = TRUE)
Warning: Expected 3 pieces. Additional pieces discarded in 1435 rows [1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...].
data <- final_tibble |> 
  mutate(
    author = str_extract(work, "^(.*)\\.\\s"), # Всё до последней точки
    author = str_remove(author, "\\s$"),      # Удаляю лишний пробел в конце
    title = str_extract(work, "(?<=\\.\\s).*") # Всё после последней точки
  ) |> 
  select(-work)

Частеречная разметка

library(udpipe)
udpipe_download_model(language = "russian-gsd")
Downloading udpipe model from https://raw.githubusercontent.com/jwijffels/udpipe.models.ud.2.5/master/inst/udpipe-ud-2.5-191206/russian-gsd-ud-2.5-191206.udpipe to /Users/karinachadaeva/Desktop/HSE/1 year/text analysis/homework/hw9/russian-gsd-ud-2.5-191206.udpipe
 - This model has been trained on version 2.5 of data from https://universaldependencies.org
 - The model is distributed under the CC-BY-SA-NC license: https://creativecommons.org/licenses/by-nc-sa/4.0
 - Visit https://github.com/jwijffels/udpipe.models.ud.2.5 for model license details.
 - For a list of all models and their licenses (most models you can download with this package have either a CC-BY-SA or a CC-BY-SA-NC license) read the documentation at ?udpipe_download_model. For building your own models: visit the documentation by typing vignette('udpipe-train', package = 'udpipe')
Downloading finished, model stored at '/Users/karinachadaeva/Desktop/HSE/1 year/text analysis/homework/hw9/russian-gsd-ud-2.5-191206.udpipe'
steph <- udpipe_load_model(file = "russian-gsd-ud-2.5-191206.udpipe")
works_annotate <- udpipe_annotate(steph, data$title)
works_pos <- as_tibble(works_annotate)

Я хочу посчитать, какие части речи чаще используются в названиях научных статей и построить соответствующий график

counts <- works_pos |> 
  group_by(upos) |> 
  count() |> 
  arrange(-n)

library(ggplot2)
counts |> 
  ggplot(aes(x = reorder(upos, -n), y = n, fill = n)) +
  geom_bar(stat = "identity", show.legend = TRUE) +
  scale_fill_gradient(low = "lightblue", high = "darkblue") +
  labs(x = "Часть речи", y = "Количество", title = "Распределение частей речи") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

Как и ожидалось, преобладают имена существительные, имена собственные и имена прилагательные. И в самом деле, даже вместо глаголов в названии научных статей предпочитают использовать отглагольные имена существительные.

Какие имена собственные чаще встречаются в названиях статей?

Отберу самые частотные имена собственные

propns <- works_pos |> 
  filter(upos %in% c("PROPN")) |> 
  count(lemma) |> 
  arrange(-n)
# пришлось использовать регулярные выражения, чтобы убрать из вывода одиночные буквы и инициалы
propns_clean <- propns |> 
  filter(!grepl("\\.", lemma) & nchar(lemma) > 2)
propns_clean

Сделаю облако слов

library(wordcloud)
Loading required package: RColorBrewer
library(RColorBrewer)
pal <- RColorBrewer::brewer.pal(8, "Accent")

wordcloud(propns_clean$lemma, propns_clean$n, colors = pal, max.words = 200)

Еще один график

Теперь я хочу узнать, есть ли зависимость длины названия статьи от года публикации

data <- data |> 
  mutate(title_length = str_length(title))

average_title_length <- data |> 
  group_by(year) %>%
  summarise(mean_title_length = mean(title_length, na.rm = TRUE))

average_title_length |> 
  ggplot(aes(x = year, y = mean_title_length)) +
  geom_line(color = "lightblue", linewidth = 1) +
  geom_point(color = "tomato", linewidth = 2) +
  labs(
    title = "Зависимость средней длины названия статьи от года",
    x = "Год",
    y = "Средняя длина названия статьи"
  ) +
  theme_minimal()
Warning in geom_point(color = "tomato", linewidth = 2): Ignoring unknown
parameters: `linewidth`

Видимо, с 2016 по 2018 и с 2021 по 2022 гг. считали, что “краткость - сестра таланта”(Chekhov 1889).

Токенизация и стоп-слова

library(tidytext)
library(stopwords)
stop_words <- tibble(word = stopwords("ru"))
words <- data |> 
  unnest_tokens(word, title)

words_tidy <- words  |>  
  anti_join(stop_words) |> 
  filter(!str_detect(word, "\\."), nchar(word) > 2)  
Joining with `by = join_by(word)`
words_tidy

Абсолютная частотность

words_tidy |> 
  count(word, sort = TRUE) |> 
  slice_head(n = 15) |> 
  ggplot(aes(reorder(word, n), n, fill = n)) + 
  geom_col(show.legend = FALSE) + 
  scale_fill_gradient(low = "lightblue", high = "blue") + 
  coord_flip() +
  labs(
    title = "Топ-15 слов в датасете",
    x = "Слово",
    y = "Частота"
  ) +
  theme_minimal() 

Интересно, что в такой набор базовых филологических терминов попал Гоголь. Мы видим, что на график попали формы слов. Чтобы этого избежать, я возьму токенизированный ранее датасет, в котором есть колонка “леммы”.

other <- c("как", "его")
words2 <- works_pos |> 
  unnest_tokens(word, lemma) |> 
  anti_join(stop_words) |> 
  filter(!str_detect(word, "\\."), nchar(word) > 2) |> 
  filter(!word %in% other)
Joining with `by = join_by(word)`
words2 |> 
  count(word, sort = TRUE) |> 
  slice_head(n = 20) |> 
  ggplot(aes(reorder(word, n), n, fill = n)) + 
  geom_col(show.legend = FALSE) + 
  scale_fill_gradient(low = "lightblue", high = "blue") + 
  coord_flip() +
  labs(
    title = "Топ-20 слов в датасете",
    x = "Слово",
    y = "Частота"
  ) +
  theme_minimal()  

Получилось более репрезентативно. Доминируют базовые филологические термины (язык, литература, роман, перевод, произведение и т. п.), некоторые имена собственные (Москва, Гоголь)

использованная литература

Chekhov, Anton. 1889. Краткость — сестра таланта. Moscow: SomePublisher.