0

I have a dataframe where each row contains information about the coordinates of 8 points at a point in time:

Time x1 y1 x2 y2 x3 y3 … x8 y8

A row may look like this for example:

myData <- data.frame(time=0.1,x1=-7.79,y1=7.32,x2=-3.86,y2=-1.62,x3=-1.35,y3=-4.61,x4=-6.24,y4=-9.89,x5=-6.40,y5=2.00,x6=4.02,y6=4.77,x7=-1.42,y7=9.89,x8=6.59,y8=-8.02)

The problem I have is that ggplot only accepts 1 column name for each axis. Moreover, I would like to animate the movements of the points using gganimate, that's why I want to use ggplot. How can I do this?

I managed to animate the data by drawing a plot using the standard R plot() method for each point in time and redrawing it, but that doesn't allow me to save the animation or work with it further.

Juraj
  • 99
  • 7
  • Can you make a reproducible example? Looking at [this](https://github.com/dgrtwo/gganimate), my approach would be to melt your data (might have to use data.table to do that, as it accepts two measurement variables. Then you can add `frame = Time`. – Heroka Feb 26 '16 at 12:54
  • @Heroka I added a dataframe example to the question. I could not really add any more code because I have no idea how to make ggplot do what I want. – Juraj Feb 26 '16 at 13:08
  • 1
    Ggplot needs data in long format. Try this as a first step: `library(data.table)`; `m_dat <- melt(setDT(myData), id.var="Time",measure.vars=patterns(c("x","y")), value.names=c("x","y"))` – Heroka Feb 26 '16 at 13:40
  • Juraj - Please show what your attempting. I would suggest like Heroka that melting your data frame. I use the library tidyr and dplyr before going to ggplot2. http://blog.rstudio.org/2014/07/22/introducing-tidyr/ – mtelesha Feb 26 '16 at 13:48
  • Thank you, @Heroka, your approach worked :) – Juraj Feb 27 '16 at 12:59

2 Answers2

1

I'm just getting used to tidyr and the pipe operator, so I'll appreciate any suggestions for improving this answer:

You first need to reshape your data (as @Heroka suggested), and then to split the axis and points (they're mingled in the x1, y8 names), so you'll end with a properly shaped data frame that you can pass to ggplot:

gather(myData, "coord", "value", -time) %>% 
  separate(coord, sep = 1, into = c("axis", "val2")) %>% 
  spread(key = axis, value = value) %>% 
  ggplot(aes(x = x, y = y)) + geom_point()

I'm not familiar with gganimate, but am pretty sure that form here you can find your path...

EDIT:

You can identify each point if you change the last line of code to:

ggplot(aes(x = x, y = y, color = val2)) + geom_point()

EDIT 2:

Following @Sitbu's suggestion, I changed the first line of code

PavoDive
  • 6,322
  • 2
  • 29
  • 55
  • Excellent! I didn't know about `separate()`... Only one suggestion: in the first line, you could write `gather(myData, "coord", "value", -time)`, which is clearer and remains the same no matter how many columns there are. – Stibu Feb 26 '16 at 13:56
1

This builds on the answer by PavoDive and just adds how the animation part is done.

I define a larger data set such that there actually is something to animate:

set.seed(1544)
myData <- data.frame(seq(0, 1, by = 0.1),
                     matrix(runif(11*8*2, -10, 10), nrow = 11))
names(myData) <- c("time", paste0(c("x", "y"), rep(1:8, each = 2)))

and then I use PavoDive's code to convert to long format:

library(tidyr)
library(magrittr)
long_data <- 
gather(myData, "coord", "value", -time) %>% 
  separate(coord, sep = 1, into = c("axis", "val2")) %>% 
  spread(key = axis, value = value)

Using gg_animate() is luckily rather simple. All you have to do is add a frame aesthetic:

p <- ggplot(long_data, aes(x = x, y = y, frame = time)) + geom_point()
gg_animate(p, "animation.gif")

enter image description here

If you are using RStudio, you can omit the file name in gg_animate() to show the plot in RStudio's plot pane.

Stibu
  • 15,166
  • 6
  • 57
  • 71
  • I've never had the need to animate a plot, so I thought `gganimate` was rather complex. It's very simple! One thing that may come handy is fixing the axis limits, so viewer can, in fact, realize the movement of each point for each time step. – PavoDive Feb 26 '16 at 14:14
  • It is ineed surprisingly simple. So we both learnt something! Regarding your comment: the axes are kept constant. Imagine that you would map `time` to `colour` instead of `frame`. Then, `ggplot()` would choose the axes such that the dots of all colours are shown in the plot. The same is done when you map `time` to `frame`. You can try this by modifying `long_data` as follows: `long_data[long_data$time == 0.5, "x"] <- 0`. The x-axis range is still the same in all the frames. Still simple! – Stibu Feb 26 '16 at 14:22