Benjamin Caldwell
2012-Mar-29 22:49 UTC
[R] scalar assignment within a vector within function
Hello, I'm trying to create a vector of r^2 values for using a function which I will run in a "for" loop. Example: per<-rnorm(100,.5,.2)^2 x<-rnorm(100,10,5) y<-rnorm(100,20,5) fr<-data.frame(x,y,per) test<-rep(0,9) plotter<-function(i){ temp.i<-fr[fr$per <=(i*.10),] with(temp.i, plot(x, y, main=(i*.10),)) mod<-lm(y~x-1,data=temp.i) r2<-summary(with(temp.i, lm(y~x)))$adj.r.squared legend("bottomright", legend=signif(r2), col="black") test[i]<-r2 print(r2) abline(mod) rm(temp.i) rm(i) rm(mod) rm(r2) } test Test comes up as the original vector of zeros. I know r2 is created for a couple reasons (print works, and they show up on the graphs). Also, if I run the function line by line with i assigned a number, test[i] is assigned as it should be. However, if I call the function, plotter(i), test is not modified, although the r^2 prints. Mystified. What am I missing? [[alternative HTML version deleted]]
Hello, btc1 wrote> > Hello, > > I'm trying to create a vector of r^2 values for using a function which I > will run in a "for" loop. Example: > > per<-rnorm(100,.5,.2)^2 > x<-rnorm(100,10,5) > y<-rnorm(100,20,5) > fr<-data.frame(x,y,per) > > test<-rep(0,9) > > plotter<-function(i){ > temp.i<-fr[fr$per <=(i*.10),] > with(temp.i, plot(x, y, main=(i*.10),)) > mod<-lm(y~x-1,data=temp.i) > r2<-summary(with(temp.i, lm(y~x)))$adj.r.squared > legend("bottomright", legend=signif(r2), col="black") > test[i]<-r2 > print(r2) > abline(mod) > rm(temp.i) > rm(i) > rm(mod) > rm(r2) > } > > test > > Test comes up as the original vector of zeros. I know r2 is created for a > couple reasons (print works, and they show up on the graphs). Also, if I > run the function line by line with i assigned a number, test[i] is > assigned > as it should be. However, if I call the function, plotter(i), test is not > modified, although the r^2 prints. > > Mystified. What am I missing? > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help@ 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. >You're changing a copy in the function's environment only, not in the environment where it was created. To have the changed copy, have the function return it. (By the way, when the function returns, it rm 'temp.i', etc.) There is a way of making global assignments but don't do this test[i] <<- r2 without readind P. Burns, The R Inferno, Circle 6. http://www.burns-stat.com/pages/Tutor/R_inferno.pdf Hope this helps, Rui Barradas -- View this message in context: http://r.789695.n4.nabble.com/scalar-assignment-within-a-vector-within-function-tp4517310p4517387.html Sent from the R help mailing list archive at Nabble.com.
Peter Langfelder
2012-Mar-29 23:40 UTC
[R] scalar assignment within a vector within function
On Thu, Mar 29, 2012 at 3:49 PM, Benjamin Caldwell <btcaldwell at berkeley.edu> wrote:> Hello, > > I'm trying to create a vector of r^2 values for using a function which I > will run in a "for" loop. Example: > > per<-rnorm(100,.5,.2)^2 > x<-rnorm(100,10,5) > y<-rnorm(100,20,5) > fr<-data.frame(x,y,per) > > test<-rep(0,9) > > plotter<-function(i){ > temp.i<-fr[fr$per <=(i*.10),] > with(temp.i, plot(x, y, main=(i*.10),)) > mod<-lm(y~x-1,data=temp.i) > r2<-summary(with(temp.i, lm(y~x)))$adj.r.squared > legend("bottomright", legend=signif(r2), col="black") > test[i]<-r2 > print(r2) > abline(mod) > rm(temp.i) > rm(i) > rm(mod) > rm(r2) > } > > test > > Test comes up as the original vector of zeros. I know r2 is created for a > couple reasons (print works, and they show up on the graphs). Also, if I > run the function line by line with i assigned a number, test[i] is assigned > as it should be. However, if I call the function, plotter(i), test is not > modified, although the r^2 prints. > > Mystified. What am I missing?Add the line test to the end of your function; this will cause the function to return the value of the vector test. Then call the function as test = plotter(1) or something. You're missing the fact that in R all function arguments are passed by value (think of them as being copied) and your function assigns a value in a local copy of the vector test. This copy is discarded when the function exits. The global copy is not modified. Of course, when you step through the lines individually (not within a function call), you work with the global test. HTH Peter
Benjamin Caldwell
2012-Mar-30 19:56 UTC
[R] scalar assignment within a vector within function
Ok, I've modified it as suggested so as to not pass to the global. Thanks for the suggestions, and the link to the interesting reading. On Fri, Mar 30, 2012 at 12:26 PM, William Dunlap <wdunlap@tibco.com> wrote:> I think you will be happier in the long run if you use the approach > Peter suggested. Do not use <<-, remove the calls to rm() > from your function (because they do nothing useful -- all variables > in a function disappear when the function is done), have it return > its local variable 'test' and call it as > test5 <- plotter(5) > > If you treat all variables as globals you will run into trouble. > > Bill Dunlap > Spotfire, TIBCO Software > wdunlap tibco.com > > > > -----Original Message----- > > From: r-help-bounces@r-project.org [mailto:r-help-bounces@r-project.org] > On Behalf > > Of Benjamin Caldwell > > Sent: Friday, March 30, 2012 12:09 PM > > To: Peter Langfelder > > Cc: r-help > > Subject: Re: [R] scalar assignment within a vector within function > > > > Thanks all - ended up going with > > test<<-test > > > > On Thu, Mar 29, 2012 at 4:40 PM, Peter Langfelder < > > peter.langfelder@gmail.com> wrote: > > > > > On Thu, Mar 29, 2012 at 3:49 PM, Benjamin Caldwell > > > <btcaldwell@berkeley.edu> wrote: > > > > Hello, > > > > > > > > I'm trying to create a vector of r^2 values for using a function > which I > > > > will run in a "for" loop. Example: > > > > > > > > per<-rnorm(100,.5,.2)^2 > > > > x<-rnorm(100,10,5) > > > > y<-rnorm(100,20,5) > > > > fr<-data.frame(x,y,per) > > > > > > > > test<-rep(0,9) > > > > > > > > plotter<-function(i){ > > > > temp.i<-fr[fr$per <=(i*.10),] > > > > with(temp.i, plot(x, y, main=(i*.10),)) > > > > mod<-lm(y~x-1,data=temp.i) > > > > r2<-summary(with(temp.i, lm(y~x)))$adj.r.squared > > > > legend("bottomright", legend=signif(r2), col="black") > > > > test[i]<-r2 > > > > print(r2) > > > > abline(mod) > > > > rm(temp.i) > > > > rm(i) > > > > rm(mod) > > > > rm(r2) > > > > } > > > > > > > > test > > > > > > > > Test comes up as the original vector of zeros. I know r2 is created > for a > > > > couple reasons (print works, and they show up on the graphs). Also, > if I > > > > run the function line by line with i assigned a number, test[i] is > > > assigned > > > > as it should be. However, if I call the function, plotter(i), test > is not > > > > modified, although the r^2 prints. > > > > > > > > Mystified. What am I missing? > > > > > > > > > Add the line > > > > > > test > > > > > > to the end of your function; this will cause the function to return > > > the value of the vector test. > > > > > > Then call the function as > > > > > > test = plotter(1) > > > > > > or something. > > > > > > You're missing the fact that in R all function arguments are passed by > > > value (think of them as being copied) and your function assigns a > > > value in a local copy of the vector test. This copy is discarded when > > > the function exits. The global copy is not modified. Of course, when > > > you step through the lines individually (not within a function call), > > > you work with the global test. > > > > > > HTH > > > > > > Peter > > > > > > > [[alternative HTML version deleted]] > > > > ______________________________________________ > > 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. >[[alternative HTML version deleted]]