Hi, I have the following data: Path_Number <- 5 ID.Path <- c(1:Path_Number) # Make vector of ID's. No_of_X <- sample(50:550, length(ID.Path), replace=TRUE) # X <- split(sample(1:10000, sum(No_of_X), replace=TRUE), rep(ID.Path, No_of_X)) Y <- lapply(X,function(x) sample(x, round(runif(1, min=10, max=50)))) X and Y are both lists, and I've made the following function to work on that data as part of a simulation I'm building: Mutate<-function(x){ l<-0 for(i in x){ l2<-0 l<-l+1 for(i in x[[l]]){ l2<-l2+1 if(runif(1) < 0.9) ifelse(runif(1) <0.5, x[[l]][l2] <- x[[l]][l2]+1, x[[l]][l2] <- x[[l]][l2]-1) } } return(x) } I call this with Effectors<-Mutate(X) The function is designed to alter the values of each element in X by either + or - 1 (50:50 chance wether + or -). However Y, elements of which are a subset of the corresponding elements of X, need to be consistent i.e. if a value in X is changed, and that value is part of the Y subset, then the value in Y also needs to be changed. however, since Y is a smaller subset it will not be indexed the same. My idea was to include in the function an if statement that checks if Y contains the value to be changed, removes it, and then after the value in X is changed, put the new value in Y. I attempted this with: Mutate<-function(x,y){ l<-0 for(i in x){ l2<-0 l<-l+1 for(i in x[[l]]){ l2<-l2+1 if(runif(1) < 0.9){ if(x[[l]][l2] %in% y[[l]] == TRUE){ y[[l]]<-[which(y[[l]]!=x[[l]][l2])] if(runif(1) <0.5){ x[[l]][l2] <- x[[l]][l2]+1 y[[l]]<-append(x[[l]][l2]) }else{ x[[l]][l2] <- x[[l]][l2]-1 y[[l]]<-append(x[[l]][l2]) } } ifelse(runif(1) <0.5, x[[l]][l2] <- x[[l]][l2]+1, x[[l]][l2] <- x[[l]][l2]-1) } } } return(list(x,y)) } Bit of an eyesore so I've put the altered stuff in bold. I've basically taken what the ifelse statement does in the first function, (which is still there and run if Y does not contain the X value being altered) and broken it down into an if and an else segment with multiple operations in curly braces to accommodate the extra actions needed to alter Y as well as X. This was all I could think of to keep changes between the two "in sync", however this does not work when I try to load the function into workspace: Error: unexpected '}' in "}" I hope someone can point out what it is I've done that isn't working, or a better way to do this. Best Wishes, Ben W. UEA (ENV) & The Sainsbury Laboratory. [[alternative HTML version deleted]]
Le mardi 27 novembre 2012 ? 16:45 +0000, Benjamin Ward (ENV) a ?crit :> Hi, > > I have the following data: > > Path_Number <- 5 > ID.Path <- c(1:Path_Number) # Make vector of ID's. > No_of_X <- sample(50:550, length(ID.Path), replace=TRUE) # > X <- split(sample(1:10000, sum(No_of_X), replace=TRUE), rep(ID.Path, > No_of_X)) > Y <- lapply(X,function(x) sample(x, round(runif(1, min=10, max=50)))) > > X and Y are both lists, and I've made the following function to work > on that data as part of a simulation I'm building: > > Mutate<-function(x){ > l<-0 > for(i in x){ > l2<-0 > l<-l+1 > for(i in x[[l]]){ > l2<-l2+1 > if(runif(1) < 0.9) ifelse(runif(1) <0.5, x[[l]][l2] <- > x[[l]][l2]+1, x[[l]][l2] <- x[[l]][l2]-1) > } > } > return(x) > } > > I call this with Effectors<-Mutate(X) > The function is designed to alter the values of each element in X by > either + or - 1 (50:50 chance wether + or -). However Y, elements of > which are a subset of the corresponding elements of X, need to be > consistent i.e. if a value in X is changed, and that value is part of > the Y subset, then the value in Y also needs to be changed. however, > since Y is a smaller subset it will not be indexed the same. My idea > was to include in the function an if statement that checks if Y > contains the value to be changed, removes it, and then after the value > in X is changed, put the new value in Y. I attempted this with:You should really read about vectorizing operations: you can most likely get the same results in R using only a few lines, with a much better performance. runif(length(x)) will directly give you a vector of the needed length, and you can add or subtract 1 from x in one line: new.x <- ifelse(runif(length(x)) > .5, x + 1, x - 1) y[match(x, y, nomatch=0)] <- new.x y <- ifelse(y %in% x, new.x[match(y, x)], y) x <- new.x This is of course a proof of concept, I'm not sure this is really what you asked for. See below for some debugging of your code.> > > Mutate<-function(x,y){ > l<-0 > for(i in x){ > l2<-0 > l<-l+1 > for(i in x[[l]]){ > l2<-l2+1 > if(runif(1) < 0.9){ > if(x[[l]][l2] %in% y[[l]] == TRUE){ > y[[l]]<-[which(y[[l]]!=x[[l]][l2])]Bug is here: ^ You should specify an object to index.> if(runif(1) <0.5){ > x[[l]][l2] <- x[[l]][l2]+1 > y[[l]]<-append(x[[l]][l2]) > }else{ > x[[l]][l2] <- x[[l]][l2]-1 > y[[l]]<-append(x[[l]][l2]) > } > } > ifelse(runif(1) <0.5, x[[l]][l2] <- x[[l]][l2]+1, x[[l]][l2] > <- x[[l]][l2]-1) > } > } > } > return(list(x,y)) > } > > Bit of an eyesore so I've put the altered stuff in bold. I've > basically taken what the ifelse statement does in the first function, > (which is still there and run if Y does not contain the X value being > altered) and broken it down into an if and an else segment with > multiple operations in curly braces to accommodate the extra actions > needed to alter Y as well as X. This was all I could think of to keep > changes between the two "in sync", however this does not work when I > try to load the function into workspace: > > Error: unexpected '}' in "}"You should have copied the full output. This is only the last error message: once an error happens, the whole syntax is broken and every bracket can trigger an error. Only by looking at the first error you can understand what's the problem. Regards> I hope someone can point out what it is I've done that isn't working, > or a better way to do this. > > Best Wishes, > > Ben W. > > UEA (ENV) & The Sainsbury Laboratory. > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
Ben, You can use the sample() function to randomly add -1, 0, or 1 to each observation, and control for the probability of mutation at the same time. Then you can use the match() function to make sure that any mutations in X are carried through to Y in the same way. I wrote the function to do each list element separately. So a gene in X[[1] and Y[[1]] will be mutated in the same way, but the same gene in X[[2]] and Y[[2]] may be mutated in a different way. Not sure if that is what you want. Mutate <- function(x, y, prob.mutate=0.9) { ux <- unique(c(x, y)) new.ux <- ux + sample(c(-1, 0, 1), size=length(ux), replace=TRUE, prob=c(prob.mutate/2, 1-prob.mutate, prob.mutate/2)) new.x <- new.ux[match(x, ux)] new.y <- new.ux[match(y, ux)] list(xm=new.x, ym=new.y) } Effectors <- lapply(seq(X), function(i) Mutate(X[[i]], Y[[i]])) Jean "Benjamin Ward (ENV)" <B.Ward@uea.ac.uk> wrote on 11/27/2012 10:45:23 AM:> > Hi, > > I have the following data: > > Path_Number <- 5 > ID.Path <- c(1:Path_Number) # Make vector of ID's. > No_of_X <- sample(50:550, length(ID.Path), replace=TRUE) # > X <- split(sample(1:10000, sum(No_of_X), replace=TRUE),rep(ID.Path,No_of_X))> Y <- lapply(X,function(x) sample(x, round(runif(1, min=10, max=50)))) > > X and Y are both lists, and I've made the following function to work > on that data as part of a simulation I'm building: > > Mutate<-function(x){ > l<-0 > for(i in x){ > l2<-0 > l<-l+1 > for(i in x[[l]]){ > l2<-l2+1 > if(runif(1) < 0.9) ifelse(runif(1) <0.5, x[[l]][l2] <- x[[l]] > [l2]+1, x[[l]][l2] <- x[[l]][l2]-1) > } > } > return(x) > } > > I call this with Effectors<-Mutate(X) > The function is designed to alter the values of each element in X by > either + or - 1 (50:50 chance wether + or -). However Y, elements of > which are a subset of the corresponding elements of X, need to be > consistent i.e. if a value in X is changed, and that value is part > of the Y subset, then the value in Y also needs to be changed. > however, since Y is a smaller subset it will not be indexed the > same. My idea was to include in the function an if statement that > checks if Y contains the value to be changed, removes it, and then > after the value in X is changed, put the new value in Y. I attemptedthiswith:> > > Mutate<-function(x,y){ > l<-0 > for(i in x){ > l2<-0 > l<-l+1 > for(i in x[[l]]){ > l2<-l2+1 > if(runif(1) < 0.9){ > if(x[[l]][l2] %in% y[[l]] == TRUE){ > y[[l]]<-[which(y[[l]]!=x[[l]][l2])] > if(runif(1) <0.5){ > x[[l]][l2] <- x[[l]][l2]+1 > y[[l]]<-append(x[[l]][l2]) > }else{ > x[[l]][l2] <- x[[l]][l2]-1 > y[[l]]<-append(x[[l]][l2]) > } > } > ifelse(runif(1) <0.5, x[[l]][l2] <- x[[l]][l2]+1, x[[l]][l2] > <- x[[l]][l2]-1) > } > } > } > return(list(x,y)) > } > > Bit of an eyesore so I've put the altered stuff in bold. I've > basically taken what the ifelse statement does in the first > function, (which is still there and run if Y does not contain the X > value being altered) and broken it down into an if and an else > segment with multiple operations in curly braces to accommodate the > extra actions needed to alter Y as well as X. This was all I could > think of to keep changes between the two "in sync", however this > does not work when I try to load the function into workspace: > > Error: unexpected '}' in "}" > > I hope someone can point out what it is I've done that isn't > working, or a better way to do this. > > Best Wishes, > > Ben W. > > UEA (ENV) & The Sainsbury Laboratory.[[alternative HTML version deleted]]