Visualisation des voyelles avec R


Crée : 2022/05 ; dernière mise à jour : 2024/02/06

Comme toujours, il y a plusieurs façons de visualiser des voyelles avec R. Par exemple, on peut utiliser des extensions spécifiques (phonR et vowels). Toutefois, c’est facile de le faire sans ces extensions, c.-à-d., en utilisant seulement ggplot2. Si vous voulez créer un trapèze vocalique, consultez l’appli ici.


Étape 1 : Principes fondamentaux

Pour l’exemple ci-dessous, je simule quelques voyelles en générant des valeurs aléatoires pour F1 et F2 (à partir de deux distributions normales). Naturellement, vous pouvez importer des données réelles (p. ex., phonR). D’abord, voyons un graphique de ggplot standard.

Code
library(tidyverse)

set.seed(10)

vowels = tibble(vowel = rep(c("a", "e", "i", "o", "u"), each = 50),
                
                F1 = c(rnorm(50, mean = 800, sd = 100), 
                       rnorm(50, mean = 600, sd = 100), 
                       rnorm(50, mean = 350, sd = 100), 
                       rnorm(50, mean = 600, sd = 100), 
                       rnorm(50, mean = 350, sd = 100)),
                
                F2 = c(rnorm(50, mean = 1500, sd = 150), 
                       rnorm(50, mean = 2000, sd = 150), 
                       rnorm(50, mean = 2500, sd = 150), 
                       rnorm(50, mean = 1000, sd = 150), 
                       rnorm(50, mean = 800, sd = 150)))


ggplot(data = vowels, aes(x = F2, y = F1, color = vowel, label = vowel)) + 
    geom_text() +
    theme_classic(base_size = 15) +
    theme(text = element_text(size = 13))

Étape 2 : Axes

F1 et F2 inversés

Le premier problème avec le graphique ci-dessus est les axes, qui doivent être inversés. En plus, les directions des axes doivent aussi être changées pour que l’origine de F1 et de F2 soit le coin supérieur droit. C’est très facile de le faire avec les fonctions scale_y_reverse() et scale_x_reverse(). Vous pouvez également utiliser la fonction formants() de l’extension `Fonology’.

Code
library(Fonology)

ggplot(data = vowels, aes(x = F2, y = F1, color = vowel, label = vowel)) + 
    geom_text() + 
    formants() +
    theme(legend.position = "none",
          text = element_text(size = 13)) +
    theme_classic()

Position des axes

C’est facile de changer les axes : on ajoute un argument positionnel aux fonctions scale_x_reverse() et scale_y_reverse().

Code
ggplot(data = vowels, aes(x = F2, y = F1, color = vowel, label = vowel)) + 
    geom_text() + 
    formants() +
    theme(legend.position = "none",
          text = element_text(size = 13)) +
    theme_classic()

Tout le reste est simple. Vous pouvez ajuster la mise en forme au besoin, ajouter des barres d’erreurs, etc. Si vous ne savez pas comment le faire, continuez à lire.

Étape 3 : Extras

Graphique de densité

On peut utiliser la fonction geom_density_2d() pour accentuer les densités des voyelles.

Code
ggplot(data = vowels, aes(x = F2, y = F1, color = vowel, label = vowel)) + 
    geom_text() + 
    formants() +
    geom_density_2d() +
    theme(legend.position = "none",
          text = element_text(size = 13)) +
    theme_classic()

Barre d’erreurs doubles

Il se peut que vous vouliez avoir deux barres d’erreurs par voyelle en utilisant les moyennes de F1 et F2 ainsi que leurs erreurs type. Ici, on va employer geom_errorbar() et geom_errorbarh(). Il faut calculer les moyennes et les erreurs type avant de les ajouter au graphique.

Code
# First, create summary table (tibble) with means and standard errors
# I'm using dplyr here (since I loaded tidyverse above)

means = vowels %>% 
    group_by(vowel) %>% 
    summarize(meanF1 = mean(F1),
              meanF2 = mean(F2),
              seF1 = sd(F1)/sqrt(n()),
              seF2 = sd(F2)/sqrt(n()))

Maintenant, on a toutes les informations nécessaires pour créer notre graphique avec les moyennes et leurs erreurs type.

Code
ggplot(data = means, aes(x = meanF2, y = meanF1, color = vowel)) + 
    geom_errorbar(aes(ymin = meanF1 - seF1, ymax = meanF1 + seF1), 
                  width = 0, linewidth = 1) + 
    geom_errorbarh(aes(xmin = meanF2 - seF2, xmax = meanF2 + seF2), 
                   height = 0, linewidth = 1) +
    formants() +
    theme(legend.position = "none",
          text = element_text(size = 13)) +
    theme_classic()

Notre graphique est pratiquement complet, mais il faut décider comment indiquer les voyelles. Maintenant, on utilise des couleurs, mais peut-être on veut déplacer les voyelles de la légende au graphique, à côté des barres d’erreurs.

Plus d’adaptations

Pour ce faire, on va employer les fonctions geom_text() ou geom_label(), qui nous permettent d’afficher des étiquettes de texte, et après ajuster leurs positions au besoin. Notez qu’il faut avoir un autre argument dans aes(), c.-à-d., label. Finalement, on veut supprimer la légende, vu que l’on utilise geom_text().

Code
ggplot(data = means, aes(x = meanF2, y = meanF1, label = vowel)) + 
    geom_errorbar(aes(ymin = meanF1 - seF1, ymax = meanF1 + seF1), width = 0, size = 1) + 
    geom_errorbarh(aes(xmin = meanF2 - seF2, xmax = meanF2 + seF2), height = 0, size = 1) +
    geom_text(position = position_nudge(x = 50, y = 50), size = 5, color = "black") + 
    formants() +
    theme_classic(base_size = 15) +
    theme(text = element_text(size = 13))
#> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` instead.

On peut aussi changer la police, les couleurs, etc. Enfin, il faut ajuster les étiquettes de nos axes (notez le \n pour ajouter un retour à la ligne). Enfin, on va annexer «Hz» à chaque valeur dans les axes x et y.

Code
library(scales)

ggplot(data = means, aes(x = meanF2, y = meanF1, label = vowel)) + 
    geom_errorbar(aes(ymin = meanF1 - seF1, ymax = meanF1 + seF1), width = 0, size = 1) + 
    geom_errorbarh(aes(xmin = meanF2 - seF2, xmax = meanF2 + seF2), height = 0, size = 1) +
    geom_text(position = position_nudge(x = 50, y = 50), size = 5, color = "orange") + 
    scale_y_reverse(position = "right", labels = unit_format(unit = "Hz", sep = "")) + 
    scale_x_reverse(position = "top", labels = unit_format(unit = "Hz", sep = "")) + 
    labs(x = "F2\n",
         y = "F1\n") + 
    theme_classic(base_size = 15) +
    theme(text = element_text(size = 13))

Détails finaux

Finalement, on va revisiter notre graphique de densité pour ajuster sa mise en forme. Notez que je vais changer la taille de la police, ajouter un peu de transparence à la densité, et ajuster les axes pour avoir un aspect propre.

Code
ggplot(data = vowels, aes(x = F2, y = F1, color = vowel, label = vowel)) + 
    geom_text(size = 6) + # Font size for vowels
    scale_y_reverse(position = "right", 
                    labels = unit_format(unit = "Hz", sep = ""),
                    breaks = seq(100, 1000, 250)) + 
    scale_x_reverse(position = "top", 
                    labels = unit_format(unit = "Hz", sep = ""),
                    breaks = seq(200, 3000, 500)) + 
    labs(x = "F2\n",
         y = "F1\n",
         title = "Final plot (A)") + 
    geom_density_2d(alpha = 0.3) +
    coord_cartesian(xlim = c(3000, 200), 
                    ylim = c(1000, 100)) +
    theme_classic(base_size = 15) +
    theme(legend.position = "none",
          plot.title = element_text(hjust = 0.5), # Center plot title
          text = element_text(size = 13))

Maintenant avec des ellipses semi-transparentes.

Code
ggplot(data = vowels, aes(x = F2, y = F1, color = vowel, label = vowel)) + 
    geom_text(size = 6) + # Font size for vowels
    scale_y_reverse(position = "right", 
                    labels = unit_format(unit = "Hz", sep = ""),
                    breaks = seq(100, 1000, 250)) + 
    scale_x_reverse(position = "top", 
                    labels = unit_format(unit = "Hz", sep = ""),
                    breaks = seq(200, 3000, 500)) + 
    labs(x = "F2\n",
         y = "F1\n",
         title = "Final plot (B)") + 
    stat_ellipse(type = "norm", alpha = 0.3) +
    coord_cartesian(xlim = c(3000, 200), 
                    ylim = c(1000, 100)) +
    theme_classic(base_size = 15) +
    theme(legend.position = "none",
          text = element_text(size = 13),
          plot.title = element_text(hjust = 0.5))

Enfin, on peut conserver les ellipses et afficher seulement les valeurs moyennes de F1 et F2. Pour ce faire, la fonction geom_label() a besoin de la variable means créé ci-dessus (mais stat_ellipse() a encore besoin de la variable vowels, donc on va travailler avec deux ensembles de données).

Code
ggplot(data = means, aes(x = meanF2, y = meanF1, color = vowel, label = vowel)) + 
    geom_label(size = 6, fill = "white") + # Font size for vowels
    scale_y_reverse(position = "right", 
                    labels = unit_format(unit = "Hz", sep = ""),
                    breaks = seq(100, 1000, 250)) + 
    scale_x_reverse(position = "top", 
                    labels = unit_format(unit = "Hz", sep = ""),
                    breaks = seq(200, 3000, 500)) + 
    labs(x = "F2\n",
         y = "F1\n",
         title = "Final plot (C)") + 
    stat_ellipse(data = vowels, aes(x = F2, y = F1), type = "norm") +
    coord_cartesian(xlim = c(3000, 200), 
                    ylim = c(1000, 100)) +
    theme_classic(base_size = 15) +
    theme(legend.position = "none",
          plot.title = element_text(hjust = 0.5), 
          text = element_text(size = 13))


Copyright © 2024 Guilherme Duarte Garcia