1

I am trying to generate a "fake" data set of spatially limited random walks, i.e., at each timestep, the individual will randomly move an arbitrary distance x and y, but these values need to be constrained to my arena (xlim and ylim)--I don't particularly care what happens (reflection or follow the wall) when the individual hits an edge, but they can't go past the edge.

All the code runs and the function "walker" gives new and different values each time it is separately run, but when I put it through a purrr::map, the values are just repeated for each individual.

I have cobbled this together from a few sources and I'm sure it could be streamlined substantially--eventually, I'll want n.times to be much greater (and the eventual goal will be to calculate the amount of time*# individuals visiting particular grid squares), but step one is to get the individuals to have different movement records!

library(tidyverse) n.times<-10 OUT <-data.frame(x.a = vector("numeric", n.times),y.a = vector("numeric", n.times)) walker <- function(n.times, xlim=c(0,100), ylim=c(0,30), start=c(0,0), stepsize=c(1,1)) { ## extract starting point x <- start[1] y <- start[2] for (i in 1:n.times) { repeat { ## pick jump sizes xi <- stepsize[1]*sample(rnorm(n = n.times, mean = 0, sd = .5),1) yi <- stepsize[2]*sample(rnorm(n = n.times, mean = 0, sd = .5),1) ## new candidate locations newx <- x+xi newy <- y+yi ## IF new locations are within bounds, then ## break out of the repeat{} loop (otherwise ## try again) if (newx>xlim[1] && newx<xlim[2] && newy>ylim[1] && newy<ylim[2]) break } ## set new location to candidate location x <- newx y <- newy OUT[i,"x.a"] <-x OUT[i, "y.a"] <-y } return(OUT) } #generate fake fish fish<-data.frame(fish=as.character(letters[1:10])) #apply walker to fake fish fishmoves <- fish %>% mutate(data= map(.,~walker(10))) %>% unnest(data) 

1 Answer 1

1

When you call map, it needs to iterate through the same number as the length of your data.frame. You used the magrittr . which will be the whole data.frame in your case, making it 1, hence, the 1 value is replicated.

You can do two things:

library(dplyr) library(tidyr) library(purrr) res = tibble(fish) %>% mutate(data=map(fish,~walker(10))) res$data[1:2] [[1]] x.a y.a 1 0.05691327 0.6609499 2 0.32432701 1.2174572 3 0.66515689 1.8964721 4 0.88173958 2.3758121 5 0.43781208 3.0526259 6 0.14187217 2.9216027 7 1.04768003 2.6636641 8 0.98632704 2.3824672 9 0.85341917 3.4224993 10 0.97703491 3.9261718 [[2]] x.a y.a 1 0.4137715 0.3202513 2 0.3973849 0.2958951 3 0.9051333 0.4163088 4 0.6249996 0.4514562 5 1.1098010 0.1973155 6 1.1208103 0.6239122 7 1.2693395 1.1020321 8 0.9213216 1.4417686 9 1.0848714 0.5382004 10 0.8635316 0.4516631 

A bit uncalled for, but useful if in later code you need to do something by group:

fish %>% group_by(fish) %>% mutate(data=map(.,~walker(10))) 

Btw, I would consider placing data.frame OUT inside the function.

Sign up to request clarification or add additional context in comments.

3 Comments

I'm not following what is going on for you in Part 1--when I run it, I get the same issue, both 1 and 2 have the same data. Adding a group_by as you do in Part 2 works for me and solves the problem. The OUT is inside the function, but outside the for loop--if Imove the OUT inside the for loop, I only get values at 1
declare the OUT data.frame inside the function walker thats what I mean. I have updated my answer with the libraries called. Might be you have something clashing. tidyverse can be a bit of overkill at times
Nope, just a dum-dum and didn't note that you replaced the . with "fish". Both are working now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.