用ggplot在R中制作2D随机漫步轨迹动画。

huangapple go评论51阅读模式
英文:

Animating 2D random walk trajectory with ggplot in R

问题

I'm trying to create an animation that shows the trajectory of a random walk on the (x, y) plane over time. Each 'step' is a move in either the vertical or horizontal direction, never both. For example, if you start at (0, 0) you have only four options: (0, 1), (0, -1), (1, 0), (-1, 0); you can never go from (0, 0) to (1, 1) in one step.

我正在尝试创建一个动画,显示随机行走在(x, y)平面上随时间的轨迹。每个'步骤'都是垂直或水平方向的移动,而不是两者兼而有之。例如,如果你从(0, 0)出发,只有四个选择:(0, 1),(0, -1),(1, 0),(-1, 0);你不能在一步中从(0, 0)到(1, 1)。

I've written the random walk generating function to ensure that steps can only be taken across one axis at a time. Here is a regular ggplot without animation of one of these random walks using geom_path() and geom_point():

我编写了随机行走生成函数,以确保每次只能沿一个轴采取步骤。这里是一个普通的ggplot,没有动画,显示了其中一个随机行走,使用了geom_path()geom_point()

用ggplot在R中制作2D随机漫步轨迹动画。

When I try to animate the walk, however, it shows diagonal lines connecting the points which is impossible.

然而,当我尝试对行走进行动画处理时,它显示连接点的对角线,这是不可能的。

用ggplot在R中制作2D随机漫步轨迹动画。

I can't figure out why this is happening. I've tried using geom_line() instead but that doesn't seem to fix the issue. The code for the animation is below:

我无法弄清楚为什么会发生这种情况。我尝试使用geom_line()代替,但似乎并没有解决问题。动画的代码如下:

ggplot(df, aes(x = x, y = y)) + 
  geom_path() +
  geom_point() +
  transition_reveal(along = ite) + # ite: numerical ordered variable in df representing the time from 0:n
  scale_x_continuous(breaks = seq(min(df$x), max(df$x), by = 1)) +
  scale_y_continuous(breaks = seq(min(df$y), max(df$y), by = 1)) +
  coord_fixed() +
  theme(panel.grid.minor = element_blank())
ggplot(df, aes(x = x, y = y)) + 
  geom_line() + # Try using geom_line() instead of geom_path()
  geom_point() +
  transition_reveal(along = ite) + # ite: numerical ordered variable in df representing the time from 0:n
  scale_x_continuous(breaks = seq(min(df$x), max(df$x), by = 1)) +
  scale_y_continuous(breaks = seq(min(df$y), max(df$y), by = 1)) +
  coord_fixed() +
  theme(panel.grid.minor = element_blank())

You can try replacing geom_path() with geom_line() in your animation code to see if it resolves the issue of diagonal lines between points.

英文:

I'm trying to create an animation that shows the trajectory of a random walk on the (x,y) plane over time. Each 'step' is a move in either the vertical or horizontal direction, never both. For example, if you start at (0,0) you have only four options: (0,1), (0,-1), (1,0), (-1,0); you can never go from (0,0) to (1,1) in one step.

I've written the random walk generating function to ensure that steps can only be taken across one axis at a time. Here is a regular ggplot without animation of one of these random walks using geom_path() and geom_point():

用ggplot在R中制作2D随机漫步轨迹动画。

When I try to animate the walk, however, it shows diagonal lines connecting the points which is impossible.

用ggplot在R中制作2D随机漫步轨迹动画。

I can't figure out why this is happening. I've tried using geom_line() instead but that doesn't seem to fix the issue. The code for the animation is below:

ggplot(df,aes(x=x,y=y)) + 
  geom_path() +
  geom_point() +
  transition_reveal(along=ite) + # ite: numerical ordered variable in df representing the time from 0:n
  scale_x_continuous(breaks = seq(min(df$x), max(df$x), by = 1)) +
  scale_y_continuous(breaks = seq(min(df$y), max(df$y), by = 1)) +
  coord_fixed() +
  theme(panel.grid.minor = element_blank())

答案1

得分: 0

你的动画帧数比你在ite上显示的状态数要小。这意味着至少偶尔,transition_reveal()必须“跳过”ite的几个状态,这导致有时绘制一条对角线。

增加动画的帧数以匹配ite的步数。你可以在显示动画时在animate()中指定,或者在保存时在anim_save()中指定。

英文:

The number of frames in your animation are smaller than the number of states you are revealing along ite. This means that at least every once in a while, transition_reveal() must "skip" across a few states of ite and this results in sometimes drawing a diagonal line.

Increase the frames in your animation to match the number of steps for ite. You can specify that in animate() when showing your animation or anim_save() when saving.

Example and Solution

Here's a demonstration using my own random walk function that works as you describe.

Note that it's useful to use {frame_along} within one of the labels in the plot that can be used to follow the particular state which is being shown.

library(ggplot2)
library(gganimate)

walk <- function(steps) {
  x <- vector(length=steps)
  y <- vector(length=steps)
  x[1] <- 0
  y[1] <- 0
  direction <- 0
  amt <- 0
  for (i in 2:steps) {
    direction <- rbinom(1, 1, 0.5)
    amt <- sample(c(-1,1), 1)
    if(direction==0) {
      x[i] <- x[i-1] + amt
      y[i] <- y[i-1]
    }
    else{
      x[i] <- x[i-1]
      y[i] <- y[i-1] + amt
    }
  }
  return(data.frame(x,y, ite=1:steps))
}

df <- walk(200)

p <- 
  ggplot(df, aes(x,y)) +
  geom_path() + geom_point() +
  labs(title="it: {frame_along}") +  # meant to write ite, but ok
  theme_bw()

a <- p + transition_reveal(along=ite)

Here's the plot without animation.

用ggplot在R中制作2D随机漫步轨迹动画。

Here's the animation. Note how the value for ite ("it: ##") is sometimes "jumping" across a few values.

用ggplot在R中制作2D随机漫步轨迹动画。

To fix, you can specify nframes= within animate() instead of just calling a directly. You will note in the output that the value for ite is incrementing every state now and not skipping. This is why you always have the straight lines.

animate(a, nframes=200)

用ggplot在R中制作2D随机漫步轨迹动画。

huangapple
  • 本文由 发表于 2023年5月11日 13:00:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76224271.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定