I have the following code: --8<---------------cut here---------------start------------->8--- d <- rep(10,10) for (i in 1:100) { a <- sample.int(length(d), size = 2) if (d[a[1]] >= 1) { d[a[1]] <- d[a[1]] - 1 d[a[2]] <- d[a[2]] + 1 } } --8<---------------cut here---------------end--------------->8--- it does what I want, i.e., modified vector d 100 times. Now, if I want to repeat this 1e6 times instead of 1e2 times, I want to vectorize it for speed, so I do this: --8<---------------cut here---------------start------------->8--- update <- function (i) { a <- sample.int(n.agents, size = 2) if (d[a[1]] >= delta) { d[a[1]] <- d[a[1]] - 1 d[a[2]] <- d[a[2]] + 1 } entropy(d, unit="log2") } system.time(entropy.history <- sapply(1:1e6,update)) --8<---------------cut here---------------end--------------->8--- however, the global d is not modified, apparently update modifies the local copy. so, 1. is there a way for a function to modify a global variable? 2. how would you vectorize this loop? thanks! -- Sam Steingold (http://sds.podval.org/) on Ubuntu 12.04 (precise) X 11.0.11103000 http://www.childpsy.net/ http://honestreporting.com http://pmw.org.il http://www.PetitionOnline.com/tap12009/ A number problem "solved" with floats turns into 1.9999999999999998 problems.
At Thu, 27 Dec 2012 15:38:08 -0500, Sam Steingold wrote:> so, > 1. is there a way for a function to modify a global variable?Use <<- instead of <-.> 2. how would you vectorize this loop?This is hard. Your function has a feedback loop: an iteration depends on the previous iteration's result. A for loop is about as good as you can do in this case. sapply might help a bit, but it is really just a for loop in disguise. Since sample.int is used to generate indexes, you might try to generate a bunch of indexes, take as many as don't overlap (i.e., collect all orthogonal updates) and do all of those updates at once. If you really need the entropy after every iteration, however, then this won't work for you either. Neal
You can use environments. Have a look at this this discussion. http://stackoverflow.com/questions/7439110/what-is-the-difference-between-parent-frame-and-parent-env-in-r-how-do-they On 27 December 2012 21:38, Sam Steingold <sds at gnu.org> wrote:> I have the following code: > > --8<---------------cut here---------------start------------->8--- > d <- rep(10,10) > for (i in 1:100) { > a <- sample.int(length(d), size = 2) > if (d[a[1]] >= 1) { > d[a[1]] <- d[a[1]] - 1 > d[a[2]] <- d[a[2]] + 1 > } > } > --8<---------------cut here---------------end--------------->8--- > > it does what I want, i.e., modified vector d 100 times. > > Now, if I want to repeat this 1e6 times instead of 1e2 times, I want to > vectorize it for speed, so I do this: > > --8<---------------cut here---------------start------------->8--- > update <- function (i) { > a <- sample.int(n.agents, size = 2) > if (d[a[1]] >= delta) { > d[a[1]] <- d[a[1]] - 1 > d[a[2]] <- d[a[2]] + 1 > } > entropy(d, unit="log2") > } > system.time(entropy.history <- sapply(1:1e6,update)) > --8<---------------cut here---------------end--------------->8--- > > however, the global d is not modified, apparently update modifies the > local copy. > > so, > 1. is there a way for a function to modify a global variable? > 2. how would you vectorize this loop? > > thanks! > > -- > Sam Steingold (http://sds.podval.org/) on Ubuntu 12.04 (precise) X 11.0.11103000 > http://www.childpsy.net/ http://honestreporting.com > http://pmw.org.il http://www.PetitionOnline.com/tap12009/ > A number problem "solved" with floats turns into 1.9999999999999998 problems. > > ______________________________________________ > 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.
In current versions of R the apply functions do not gain much (if any) in speed over a well written for loop (the for loops are much more efficient than they used to be). Using global variables could actually slow things down a little for what you are doing, if you use `<<-` then it has to search through multiple environments to find which to replace. In general you should avoid using global variables. It is best to pass all needed variables into a function as arguments, do any modifications internally inside the function on local copies, then return the modified local copy from the function (you can use a list if you want to return multiple variables). Since each iteration of your code depends on the previous iteration, vectorizing is not going to help (or even be reasonable). If you want to speed up the code then you might consider a compiled option, see the inline or rcpp packages (or others). On Thu, Dec 27, 2012 at 1:38 PM, Sam Steingold <sds@gnu.org> wrote:> I have the following code: > > --8<---------------cut here---------------start------------->8--- > d <- rep(10,10) > for (i in 1:100) { > a <- sample.int(length(d), size = 2) > if (d[a[1]] >= 1) { > d[a[1]] <- d[a[1]] - 1 > d[a[2]] <- d[a[2]] + 1 > } > } > --8<---------------cut here---------------end--------------->8--- > > it does what I want, i.e., modified vector d 100 times. > > Now, if I want to repeat this 1e6 times instead of 1e2 times, I want to > vectorize it for speed, so I do this: > > --8<---------------cut here---------------start------------->8--- > update <- function (i) { > a <- sample.int(n.agents, size = 2) > if (d[a[1]] >= delta) { > d[a[1]] <- d[a[1]] - 1 > d[a[2]] <- d[a[2]] + 1 > } > entropy(d, unit="log2") > } > system.time(entropy.history <- sapply(1:1e6,update)) > --8<---------------cut here---------------end--------------->8--- > > however, the global d is not modified, apparently update modifies the > local copy. > > so, > 1. is there a way for a function to modify a global variable? > 2. how would you vectorize this loop? > > thanks! > > -- > Sam Steingold (http://sds.podval.org/) on Ubuntu 12.04 (precise) X > 11.0.11103000 > http://www.childpsy.net/ http://honestreporting.com > http://pmw.org.il http://www.PetitionOnline.com/tap12009/ > A number problem "solved" with floats turns into 1.9999999999999998 > problems. > > ______________________________________________ > R-help@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. >-- Gregory (Greg) L. Snow Ph.D. 538280@gmail.com [[alternative HTML version deleted]]
On Dec 27, 2012, at 12:38 PM, Sam Steingold wrote:> I have the following code: > > --8<---------------cut here---------------start------------->8--- > d <- rep(10,10) > for (i in 1:100) { > a <- sample.int(length(d), size = 2) > if (d[a[1]] >= 1) { > d[a[1]] <- d[a[1]] - 1 > d[a[2]] <- d[a[2]] + 1 > } > } > --8<---------------cut here---------------end--------------->8--- > > it does what I want, i.e., modified vector d 100 times. > > Now, if I want to repeat this 1e6 times instead of 1e2 times, I want > to > vectorize it for speed, so I do this:You could get some modest improvement by "vectorizing" the two lookups, additions, and assignments into one: d[a] <- d[a]-c(1,-1) In a test with 100000 iterations, it yields about a 1.693/1.394 -1 = 21 percent improvement.> > --8<---------------cut here---------------start------------->8--- > update <- function (i) { > a <- sample.int(n.agents, size = 2) > if (d[a[1]] >= delta) { > d[a[1]] <- d[a[1]] - 1 > d[a[2]] <- d[a[2]] + 1 > } > entropy(d, unit="log2")The `unit` seems likely to throw an error since there is no argument for it to match.> } > system.time(entropy.history <- sapply(1:1e6,update)) > --8<---------------cut here---------------end--------------->8--- > > however, the global d is not modified, apparently update modifies the > local copy.You could have returned 'd' and the entropy result as a list. But what would be the point of saving 1e6 copies????> > so, > 1. is there a way for a function to modify a global variable?So if you replaced it in the global environment, you would only be seeing the result of the last iteration of the loop. What's the use of that????> 2. how would you vectorize this loop? > > thanks!-- David Winsemius, MD Alameda, CA, USA