0

I have a function to simulate genetic drift and I would like to loop it over multiple values of each parameter The function is below:

wright.fisher<-function(p,Ne,nsim,t){ N <-Ne/2 NA1 <- 2*N*p NA2 <- 2*N*(1-p) k <- matrix(0, nrow = max(2, t), ncol = nsim) k[1,] <- rep(NA1, nsim) for (j in 1:nsim) { for (i in 2:t) { k[i, j] <- rbinom(1, 2*N, prob = k[i-1, j] / (2*N)) } } k <- as.matrix(k/(2*N)) t(k) } 

I've attempted to loop it over t (generations of drift), but that fails, the following is my code:

locifreq<-runif(49, .4, 0.8) gen <- 2:99 looppop<-list() for (i in 2:length(gen)){ looppop[i]<-lapply(locifreq,wright.fisher,3000,4,gen[i]) } 

Doing that results in an error for each iteration -

> warnings() Warning messages: 1: In pop[i] <- lapply(locifreq, wright.fisher, 3000, 4, ... : number of items to replace is not a multiple of replacement length 2: In pop[i] <- lapply(locifreq, wright.fisher, 3000, 4, ... : number of items to replace is not a multiple of replacement length 

I suspect that the issue may be in storing the output into a matrix, and perhaps the function isn't accessing the matrix correctly, but i'm not sure.

Thanks!

2
  • 1
    It's a bit difficult to help without any sample data and a reproducible example. I noticed that you declare looppop but then populate pop inside the for loop. Can you please edit your question to include a minimal reproducible example that reproduces the warning. Commented Mar 21, 2018 at 0:30
  • I reproduced this example and it worked for me on R v3.4.3, generating a 98 element list of lists, where the size of each element grows in each step. Commented Mar 21, 2018 at 3:21

2 Answers 2

1

You have to add list() inside any for loop that populates a new list inside the loop:

locifreq<-runif(49, .4, 0.8) gen <- 2:99 looppop<-list() for (i in 2:length(gen)){ looppop[i]<-list(lapply(locifreq,wright.fisher,3000,4,gen[i])) # note the list( addition } 

enter image description here

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

3 Comments

The real answer is the difference between simplifying and preserving. [ will simplify and [[ will preserve. My answer below produces the exact same result as this answer, which can be tested using set.seed and identical. The reason the poster's code didn't work was because he asked for simplification with [ instead of preserve with [[.
If an alternative soluton produces “the exact same result” then it is not “the real answer” it is an alternative answer.
By real answer I mean that the problem was caused by simplification vs preservation. Understanding the difference between preservation and simplification in lists is what allows a person to understand why the original code did not produce the right answer. The "real" answer would be to explain simplification and preservation in lists.
0

Honestly, I am not completely sure what you want but does this give you what you want? I used [[i]] on the looppop instead of [i]

locifreq<-runif(49, .4, 0.8) gen <- 2:99 looppop<-list() for (i in 2:length(gen)){ looppop[[i]]<-lapply(locifreq,wright.fisher,3000,4,gen[i]) 

When lists are concatenated, one of two things will happen: preservation or simplifications. Your code uses [ so simplification is attempted. Because your matrices at each iteration are different dimensions, simplification produces and error. But if you use [[ then the concatenation will use preservation and the result will be a list of your matrices of ever increasing size. The accepted answer changes the catenation from that of matrices to that of lists. In that case the [ is preserving a list, not a matrix and the code runs as needed.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.