Statistiques phonologiques avec r (2)
Nous avons vu précédemment comment calculer la fréquence des consonne et des voyelles. On peut aussi effectuer des calculs de fréquences d’autres éléments et autres statistiques.
Reprennons le même code et les mêmes données du lexique PsychoGLÀFF, sauf que nous gardons ici l’information de syllabation pour la suite.
library(tidyverse)
library(magrittr)
library(stringr)
library(forcats)
cons <- c("[pbtdkgmnɲŋfvszʃʒʁɥwjl]")
voy <- c("[iyueøoəɛœɔaɑ]̃?")
cv <- str_c(cons, "|", voy)
lx <- read_delim("psychoGLAFF-1.0.csv", delim = ";", col_names = F) %>%
rename(wd = X4) %>%
mutate(wd = str_replace_all(wd, "ː|'", "")) %>%
filter(str_detect(wd, str_c("^(", cv, "|\\.)+$"))) %>%
filter(!str_detect(wd, "^\\.")) %>%
filter(!str_detect(wd, "\\.$")) %>%
filter(!str_detect(wd, str_c("(^|\\.)", cons, "+(\\.|$)"))) %>%
filter(str_detect(wd, voy)) %>%
filter(!is.na(wd))
Outre la fréquence des consonnes et de voyelles, calculer la fréquence des tons par exemple ne serait pas plus compliquée, et il suffirait de rajouter une expression régulière pour les tons. Le français n’est pas une langue à tons et je n’ai malheureusement pas d’exemple sous la main.
On peut vouloir calculer la fréquence dans une position particulière. Calculons par exemple la fréquence des consonnes initiales. Le graphique est ici produit directement sans passer par les résultats intermédiaires, et les pourcentages sont calculés dans ggplot
à des fins d’exemple. Notez aussi que les mots commençant par une voyelle sont considérés comme ayant une initiale «zéro» (∅).
lx$wd %>%
str_extract("^.") %>%
str_replace(voy, "∅") %>%
tibble(ini = .) %>%
ggplot(aes(x = fct_infreq(ini), y = ..count../sum(..count..)*100, label = round(..count../sum(..count..)*100, 1))) +
geom_bar(fill = "gray", stat = "count") +
geom_text(stat = "count", vjust = -.5, size = 3.5) +
scale_y_continuous(expand = c(0,0), limits = c(0,26)) +
labs(x = NULL, y = "fréquence relative (%)") +
theme_classic() +
theme(axis.ticks.x = element_blank())
On peut aussi calculer la fréquence des patrons syllabiques, en remplaçant les consonnes par «C» et les voyelles par «V», puis en séparant chaque mot selon les frontières de syllabe. Malheureusement, on constate rapidement qu’il y a des problèmes dans la syllabation et que certains mots ne sont pas syllabés du tout. Il vaut mieux donc enlever les mots non-syllabés, qui se caractérisent par la présence de plusieurs voyelles mais d’aucune marque de frontière syllabique.
lx$wd %>%
str_replace_all(cons, "C") %>%
str_replace_all(voy, "V") %>%
str_split("\\.") %>%
unlist() %>%
str_subset("^C*VC*$") %>%
tibble(syll = .) %>%
count(syll, sort = T) %>%
mutate(pct = n/sum(n)*100) %>%
ggplot(aes(x = fct_reorder(syll, n), y = pct)) +
geom_col(fill = "gray") +
geom_text(aes(label = round(pct,2)), hjust = -.25, size = 3.5) +
labs(x = NULL, y = "fréquence relative (%)") +
scale_y_continuous(expand = c(0,0), limits = c(0,61), breaks = NULL) +
coord_flip() +
theme_classic() +
theme(axis.ticks = element_blank(), axis.line = element_blank())
De manière similaire, on peut calculer la fréquence des attaques de syllabes. Comme leur nombre est trop grand, il vaut mieux se limiter aux attaques dont la fréquence relative est supérieure à 0,5%.
lx$wd %>%
str_split("\\.") %>%
unlist() %>%
str_subset(str_c("^",cons,"*",voy,cons,"*$")) %>%
str_extract(str_c("^", cons, "+")) %>%
str_replace_na("∅") %>%
tibble(attaque = .) %>%
count(attaque, sort = T) %>%
mutate(pct = n/sum(n)*100) %>%
filter(pct > .5) %>%
ggplot(aes(x = fct_reorder(attaque, n), y = pct)) +
geom_col(fill = "gray") +
geom_text(aes(label = round(pct,2)), hjust = -.25, size = 3.5) +
labs(x = NULL, y = "fréquence relative (%)") +
scale_y_continuous(expand = c(0,0), limits = c(0,11.5), breaks = NULL) +
coord_flip() +
theme_classic() +
theme(axis.ticks = element_blank(), axis.line = element_blank())
On peut calculer la longeur des mots en nombre de syllabes, là aussi en ignorant les catégories peu représentées. Le nombre de syllabes est le nombre de marqueurs de frontière syllabique + 1 («CV.CV»: 1 + 1 = 2, «CV»: 0 + 1 = 1).
nsylls <- lx %>%
filter(!str_detect(wd, str_c(voy, "[^\\.]*", voy))) %>%
select(wd) %>%
mutate(nsyll = 1 + str_count(wd, "\\."))
nsylls %>%
count(nsyll) %>%
mutate(pct = n/sum(n)*100) %>%
filter(pct > .01) %>%
ggplot(aes(x = factor(nsyll), y = pct)) +
geom_col(fill = "gray") +
geom_text(aes(label = round(pct,2)), vjust = -.25, size = 3.5) +
annotate("text", x = 6, y = 35, label = str_c("moyenne: ", round(mean(nsylls$nsyll),1), "\nmédiane: ", median(nsylls$nsyll)), hjust = 0) +
scale_y_continuous(expand = c(0,0), limits = c(0, 40)) +
labs(x = "nombre de syllabes", y = "fréquence relative (%)") +
theme_classic()
Calculons la longueur des mots, mais cette fois-ci en nombre de segments:
nsegs <- lx %>%
select(wd) %>%
mutate(nseg = str_count(wd, cv))
nsegs %>%
count(nseg) %>%
mutate(pct = n/sum(n)*100) %>%
filter(pct > .01) %>%
ggplot(aes(x = factor(nseg), y = pct)) +
geom_col(fill = "gray") +
geom_text(aes(label = round(pct,2)), vjust = -.25, size = 3.5) +
annotate("text", x = 12, y = 15, label = str_c("moyenne: ", round(mean(nsegs$nseg),1), "\nmédiane: ", median(nsegs$nseg)), hjust = 0) +
scale_y_continuous(expand = c(0,0), limits = c(0, 20)) +
labs(x = "nombre de syllabes", y = "fréquence relative (%)") +
theme_classic()
Examinons à présent la relation entre le nombre de consonnes et de voyelles d’un mot, en ignorant dans le graphique quelques valeurs aberrantes:
ncv <- lx %>%
select(wd) %>%
mutate(nc = str_count(wd, cons), nv = str_count(wd, voy))
ncv %>%
filter(nc < max(nc)) %>%
ggplot() +
geom_count(aes(x = nv, y = nc)) +
scale_size_area() +
labs(x = "nombre de voyelles", y = "nombre de consonnes") +
scale_x_continuous(breaks = seq(0,100,1)) +
scale_y_continuous(breaks = seq(0,100,1)) +
theme_classic()
Intéressons nous enfin au rapport \frac{\text{nombre de consonnes}}{\text{nombre de voyelles}} dans chaque mot:
ncv %<>% mutate(cvr = nc/nv)
ncv %>%
ggplot(aes(cvr)) +
geom_histogram(fill = "grey", binwidth = .25) +
geom_vline(aes(xintercept = mean(cvr)), linetype = "dashed", size = .4) +
annotate(geom = "text", x = mean(ncv$cvr), y = 80000, label = "moyenne", hjust = -.1) +
scale_y_continuous(expand = c(0,0)) +
scale_x_continuous(expand = c(0,0), breaks = c(0:1, mean(ncv$cvr), 2:max(ncv$cvr)), labels = c(0:1, round(mean(ncv$cvr),2), 2:max(ncv$cvr))) +
theme_classic()