The grid library is necessary for arrow()

library(ggplot2)
library(grid)

library(dplyr)
library(knitr)
ay <- read.csv("http://jofrhwld.github.io/data/ay.csv")
head(ay) %>% kable
X Word Time F1 F2 F3 VClass N RTime LDur
1 child129 0.025925 739.771 1522.028 2309.263 ay 29 0.0000000 Long
2 child129 0.027925 742.721 1496.464 2309.456 ay 29 0.0109890 Long
3 child129 0.029925 741.999 1487.178 2313.133 ay 29 0.0219780 Long
4 child129 0.031925 738.795 1483.538 2314.338 ay 29 0.0329670 Long
5 child129 0.033925 735.457 1472.834 2305.342 ay 29 0.0439560 Long
6 child129 0.035925 734.296 1441.201 2290.184 ay 29 0.0549451 Long

ay columns:

Raw data Plot

The group = N argument is crucial for it to draw one path per vowel token.

ggplot(ay, aes(F2, F1))+
  geom_path(aes(group = N), arrow = arrow())+
  scale_y_reverse()+
  scale_x_reverse()+
  coord_fixed()

The group = N argument is crucial for it to draw one path per vowel token. Without it, this is what it would look like.

ggplot(ay, aes(F2, F1))+
  geom_path(arrow = arrow())+
  scale_y_reverse()+
  scale_x_reverse()+
  coord_fixed()+
  ggtitle("Chaos")

Smooting the raw data

These are simple loess smooths of F1 and F2 over the proportional time.

f1_mod <- loess(F1 ~ RTime, data = ay)
f2_mod <- loess(F2 ~ RTime, data = ay)

After fitting the model, you get the predicted values with predict()

pred <- data.frame(RTime = seq(0,1, length = 100))
pred$F1 <- predict(f1_mod, newdata = pred)
pred$F2 <- predict(f2_mod, newdata = pred)

Plotting again. There’s no group argument this time, since the pred data frame contains only one trajectory.

ggplot(pred, aes(F2, F1))+
  geom_path(arrow = arrow())+
  scale_y_reverse()+
  scale_x_reverse()+
  coord_fixed()

It’s still not quite optimal, since there’s no sense of how fast or slow the trajectory is. Here’s one approach

# evenly spaced indices between 1 and 99
indices <- seq(1,99, by = 5)

ggplot(pred, aes(F2, F1))+
  geom_path(arrow = arrow())+
  geom_point(data = pred[indices,])+
  scale_y_reverse()+
  scale_x_reverse()+
  coord_fixed()