For some reason I thought it would be an interesting exercise in my programming skills to try and write code to generate random walks in a two-dimensional plane. Turns out this was not super hard, so I wound up having some fun making the code relatively nice.

Below is the function that I made to model a random walk for a specified number of individuals (the argument n.org) and a specified number of time steps (the argument steps). The additional arguments specify the probability of an individual moving left (or p(right) = 1-p(left)) or the probability of moving up (where p(down) = 1-p(up)). The last argument I included to show a plot of all individuals’ paths through time.

random_walk <- function(n.org, steps, left.p = .5, up.p = .5, plot = TRUE){ require(ggplot2) whereto <- matrix(ncol = 2) for(x in 1:n.org){ walker <- matrix(c(0,0), nrow = steps+1, ncol = 2, byrow = T) for(i in 1:steps){ # left/right = 1/0 horizontal <- rbinom(1, 1, left.p) # distance 2 h.dist <- abs(rnorm(1, 0, 1)) # Horizontal Movement if(horizontal == 0){ walker[i+1,1] <- walker[i,1] + h.dist } if(horizontal == 1){ walker[i+1,1] <- walker[i,1] - h.dist } # up/down = 1/0 vertical <- rbinom(1, 1, up.p) #distance 2 v.dist <- abs(rnorm(1, 0, 1)) # Vertical Movement if(vertical == 1){ walker[i+1,2] <- walker[i,2] + v.dist } if(vertical == 0){ walker[i+1,2] <- walker[i,2] - v.dist } } whereto <- rbind(whereto, walker) } id <- rep(1:n.org, each = 1001) colnames(whereto) <- c("x" , "y") whereto <- as.data.frame(whereto) whereto <- cbind(whereto[2:nrow(whereto),], org = factor(id)) if(plot){ require(ggplot2) p <- ggplot(whereto, aes(x = x, y = y, colour = org)) p <- p + geom_path() print(p) } return(whereto) } rw.test <- random_walk(1, 1000, .5, .5)

Running this code gives a 3 column data frame with steps*n.org rows. Each row of the data frame gives the (x, y) position of a given individual (individual number is in the third column). When plot = TRUE, the function will also print out a plot of the path that is taken by each individual (color coded by individual). Note that the plotting part of this function does require ggplot2.

Each individual in this case starts at (0, 0) and follows a random walk from there.

I have also been playing around with the animation package, so the above gif was created using the saveGIF function and just iteratively creating images with n rows of the data frame. The code I used to generate this is:

require(animation) ani.options(interval = .25) saveGIF( {for(i in seq(2,1001,1)){ gp <- ggplot(rw.test, aes(x=x, y=y, col = org)) + geom_path(alpha = .5) gp <- gp + geom_point(x=rw.test[i,1], y=rw.test[i,2], col = "red") print(gp) }}, movie.name = "randowalk.gif", interval = .25, nmax =1000, ani.width = 600, ani.height = 600, outdir = getwd() )

It was not super hard to write, but it did take me a while before things worked properly.

rw.test <- random_walk(10, 1000, .5, .5) ind10.1 <- rw.test rw.test <- random_walk(10, 1000, .5, .5) ind10.2 <- rw.test rw.test <- random_walk(10, 1000, .5, .5) ind10.3 <- rw.test rw.test <- random_walk(10, 1000, .5, .5) ind10.4 <- rw.test ind10.1 <- cbind(ind10.1, group = factor("gr1")) ind10.2 <- cbind(ind10.2, group = factor("gr2")) ind10.3 <- cbind(ind10.3, group = factor("gr3")) ind10.4 <- cbind(ind10.4, group = factor("gr4")) fourgrp <- rbind(ind10.1, ind10.2, ind10.3, ind10.4) ggplot(fourgrp, aes(x=x, y=y, col = org)) + geom_path() +facet_wrap(facets = ~group, nrow = 2, ncol = 2)

The above code will generate four examples of the random walk with 10 individuals each. The plot then looks like:

Messing around with some of the animation functions in R (the animation package) again you can watch multiple individual randomly walk around the plane…

Well now I have committed to trying to do more with this, so I will be posting more about this kind of random walk stuff in the future. My plan is to (1) make the code better, more modular and more versatile, and (2) build in interactions between individuals. I think that (1) is important because it is how I become a better programmer, but the second part of the plan I find most interesting because species interactions is what I study, and I would like to find a way to incorporate this kind of thing into my research.

Having trouble running this code. Also, can this be expanded to two-dimensions?

Sorry, can a set space be set to partially set a constraint on the movement?

There is no reason why you couldn’t do that. My first thought would be to enclose the movement section of the function in an `if` statement and if the whereto object lands in the constrained section, have it rerun the step selection (could do something similar with a `while` loop, and have the simulation continue only when movement is not within the constrained section.

Which part does not seem to be working (are you getting an error message at any specific point)? As it stands this is a two-dimensional random walk, but you could presumably add n-dimensions by turning `walker` into an n-column matrix, and adding another set of “Movement” code like the Vertical or Horizontal movement section in the random_walk function.

Thank you for the nice explained integration of the random walk in the 2-dim plane.

I’m new in programming in R and had the task of an special random walk on a lattice with segmented edges. Your example helped me very well to understand the basics and what for functions are useful.

I found a litte inconsistent. Your function random_walk only works for 1000 steps, because you set the fixed number 1000 in row 43. Also for the animation you set the fixed intervall/steps at 1000.