I would like to know how can I list the outputs of my function (it prints out vectors) so that I am able to know how many steps did it require until finding the optimal solution.
I have the following code and am just wondering what should I do at the end so that when printing out the vectors, it enumerates them one at a time as well. I am new to Rstudio and do see that some operations that have to do with matrices are not common in other programming languages.
I should say that I have already defined another function such as "gradient", but my concern is about the enumeration of the outputs for this particular function.
Sd=function(b0,epsilon=1e-5){
while (norm(gradient(b0))>epsilon) {
num1=(t(b0)%*%Q%*%gradient(b0)-t(y)%*%X%*%gradient(b0))/(t(gradient(b0))%*%Q%*%gradient(b0))
num2=norm(num1)
step=num2*gradient(b0)
b0=b0-step
print(t(b0))
}
}
Thank you for any help I can get.
Here's a generic answer that will show you how to approach this. Without access to your custom functions I can't give a more direct answer. It's generally helpful to give a minimal reproducible example.
That said, my basic suggestion is to use a counter variable, increment it once each loop, and include that in your printed output.
Here's a simplified example that's based on your code, but the only operation we're doing is taking repeated square roots. Note that the arrow operator <- is the best practice for assigning values. (I promise you get used to it!)
# set up a generic function for this minimal example
get_value <- function(x){
return (sqrt(x))
}
my_function <- function(b0, epsilon = 1.1){
# set up a counter variable
i <- 0
# our main loop
while (get_value(b0) > epsilon) {
# increment the counter
i <- i + 1
# do calculations
num1 <- get_value(b0)
# update our current solution
b0 <- num1
# print a message to the console with the counter and the value
message(paste0("Iteration: ",i,"\n",
"b0: ", b0))
}
# print a final message to the console when we stop
message(paste0("Final Iteration: ",i,"\n",
"Final b0: ", b0))
}
my_function(2)
Related
Say I have a function func that takes two scalar numeric inputs and delivers a scalar numeric result, and I have the following code to calculate a result vector u, based on input numeric vector v and initial value u0 for the result vector:
u<-rep(u0,1+length(v))
for (k in 2:length(u)){
u[k]<-func(u[k-1],v[k-1])
}
Note how a component of the result vector depends not only on the corresponding element of the input vector but also on the immediately prior element of the result vector. I can see no obvious way to vectorise this.
It is common to do this sort of thing in financial simulations, for instance when projecting forward company accounts, rolling them up with interest or inflation and adding in operational cash flows each year.
For some specific instances, it is possible to find a case-specific, non-iterative coding, but I would like to know if there's a general solution.
The problem can also be coded by recursion, as follows:
calc.u<-function(v,u0){
if (length(v)<2){
func(u0,v[1]) }
else {
u.prior<-func(u0,v[-length(v),drop=FALSE])
c(u.prior,func(u.prior[length(u.prior)],v[length(v)]) )
}
u<-calc.u(v,u0)
Is there an R tactic for doing this without using either iteration or recursion, ie for vectorising it?
Answered: Thank you #MrFlick for introducing me to the Reduce function, which does exactly what I was wanting. I see that
Reduce('+',v,0,accumulate=T)[-1]
gives me
cumsum(v)
and
Reduce('*',v,0,accumulate=T)[-1]
gives me
cumprod(v)
as expected, where the [-1] is to discard the initial value.
Very nice indeed! Thanks again.
If you have this example
u0 <- 5
v <- (1:5)*2
func <- function(u,v) {u/2+v}
u <- rep(u0,1+length(v))
for (k in 2:length(u)){
u[k]<-func(u[k-1],v[k-1])
}
this is equivalent to
w <- Reduce(func, v, u0, accumulate=TRUE)
And we can check that
all(u==w)
# [1] TRUE
I'm fairly new to R and I just noticed that the first call to a function seems to bind its environment parameters. How does this work ? (Or how is it it called, so I can look it up in the doc).
E.g.:
make.power <- function(n)
{
pow <- function(x)
{
x^n
}
}
i <- 3
cube <- make.power(i)
# print(cube(3)) # uncommenting this line change the value below
i <- 2
square <- make.power(i)
print(cube(3)) # this value changes depending on whether cube(3) was called before.
print(square(3))
I'm looking for a sample explanation of what's going on, or just the name of this feature, so I can look it up.
Thanks !
everyone.
I am programming a simulation app in Shiny R and I am stuck at the for loops.
Basically, in an reactive I am calling a function that loops through a couple of other functions, like this:
In the server.R:
output.addiction <- reactive ({
SimulateMultiple(input$no.simulations, vectors(), parameters(), input$S.plus, input$q,
input$weeks, input$d, list.output)
})
The function:
SimulateMultiple <- function (no.simulations, vectors, parameters, S.plus, q, weeks, d, list.output) {
for (i in 1:no.simulations) {
thisi <- i
simulation <- SimulateAddictionComponents(vectors, parameters, S.plus, q, weeks, d) # returns list "simulation"
df.output <- BuildOutputDataframe(weeks, simulation, vectors) # returns "df.outout"
output.addiction <-BuildOutputList(df.output, simulation, list.output) # returns "output.addiction"
}
return(output.addiction)
}
And, again, the last function that creates the out put list:
BuildOutputList <- function (df.output, simulation, list.output) {
addiction <- simulation$addiction
output.w.success <- list(df.output, addiction) # includes success data
output.addition <- c(list.output, list(output.w.success)) # adds the new data to the list
return(output.addition)
}
I read about the issue online a lot, I tried to isolate some stuff, to introduce a local({}) etc. But it never works. In the end, I get a list of length 1.
I would be forever grateful, if you could help me - I have been on this for two days now.
The problem solved itself when I edited the code in the function from
output.addition <- c(list.output, list(output.w.success)) # adds the new data to the list
return(output.addition)
to
list.output <- c(list.output, list(output.w.success)) # adds the new data to the list
return(list.output)
so as to not overwrite the object every time in the loop. After all - very easy and stupid problem, but hard to spot.
Thank you for trying to help. I am happy to be corrected on all R misdemeanors.
I am not sure that I was entirely clear with my earlier post as below, so I will hope to clarify:
In the R console, my calls 'use source (etc)' to a .R file
Code within the .R file uses variables (for e.g. 'extracted info' ) ex1, ex2, ex3. These may hold strings or (a string of) numbers pulled from text.
In line with your guidance I've renamed my function to 'reset' (and ?reset indicates no other occurrences) are in scope. I'm passing both x and y which from outside the function:
#send variables ex1, ex2, ex3 together with location, loc and parse, prs to be reset with 0
reset(x<-c(loc,prs,ex1,ex2,ex3),y<-rep(c(0),length(x))) #repeats 0 in y variable as many times as there are entries for x
reset<-function(x,y){
print(c("resetting ",x," with ", y))
if (length(x) == length(y)) {x <- y
print(paste(x,"=",y),sep="") #both x and y should now be equal (to y)
} else {
paste("list lengths differ: x=",length(x)," y=",length(y),sep="")
}
}
Now both x and y are 0 but ex1, ex2 and ex3 still contain the previous values
I would like ex1, ex2 and ex3 all to be 0 before they are used in a subsequent section of code, so they don't contaminate extracted data with previous values such as:
loc<-str_locate(data[i],"=")
prs<-str_locate(data[i],",")
#extract data from the end of loc to before the occurrence of prs
ex1<-str_sub(data[i],loc[2]+1,prs[1]-1)
#cleanup
#below is simplified for example;
#in reality I wish to send ex1:ex(n) to be reset with values val1:val(n)
The desired outcome would be that back in the Rconsole >ex1 should now return 0.
Hope you can understand my dilemma and possibly help.
Say my code uses some variables to hold data extracted from a string using Stringr str_sub. The variables are temporary in that I use the values to construct other strings then they should be freed up to be used in an upcoming test: i.e. if (test==true){extract<-str_sub(string, start, end)}
For a later test, I would like extract==0; simple enough, but I have a few of these and would like to do it in one fell swoop.
I've used a for loop, but if there is a simpler way, please identify this.
My attempt is using a function:
#For variables loc, prs, ex1 and x2, set all values to 0
x<-assign(x<-c(loc, prs, ex1, ex2),y<-rep(c(0),length(x)))
#Function
assign <- function(x, y) {
if(length(x)==length(y)){
for (i in 1:length(x)){x[i]<-y[i]}
print(c("Assigned",x[i]))
return (x)
} else { print (c("list lengths differ: x=",length(x)," y=",length(y)))
}
}
The problem being that this returns x as 0, but the list of variables retain their values.
I'm a bit of a noob to both r and SO, so although I've benefitted from SO's bountiful advice on numerous occasions, this is my first question, so please be gentle. I have searched this issue, but have not found what I need in a few hours now. Hope you can help.
Beware of naming a function assign. There is already one in base-r and you will create confusion.
There are a couple of problems with your function besides its name. First, you do not need the for-loop to replace x by y, as this is a basic vectorized operation. Just use x <- y ; second, your should wrap your message in paste.
asgn <- function(x, y) {
if(length(x)==length(y)){
## This step is not needed, return(y) is better as #Rick proposed in their now deleted answer
## I am leaving it to show you how the for-loop is not needed
x<-y
return (x)
} else {
print (paste("list lengths differ: x=",length(x)," y=",length(y)))
return(x)
}
}
Then, there are a couple of problems with your function call. You use <- instead of = to specify the arguments. They are only somewhat synonymous for assigning variables, but a function argument is another matter. Finally, you are trying to use x is the definition of y in the arguments (length(x)), but this is not possible, because it is not yet defined, so it is looking for x in the parent environment. You should test your function with length(3) instead.
x<-asgn(x=c(loc, prs, ex1, ex2),y=rep(c(0),length(3)))
I know that I should avoid for-loops, but I'm not exactly sure how to do what I want to do with an apply function.
Here is a slightly simplified model of what I'm trying to do. So, essentially I have a big matrix of predictors and I want to run a regression using a window of 5 predictors on each side of the indexed predictor (i in the case of a for loop). With a for loop, I can just say something like:
results<-NULL
window<-5
for(i in 1:ncol(g))
{
first<-i-window #Set window boundaries
if(first<1){
1->first
}
last<-i+window-1
if(last>ncol(g)){
ncol(g)->last
}
predictors<-g[,first:last]
#Do regression stuff and return some result
results[i]<-regression stuff
}
Is there a good way to do this with an apply function? My problem is that the vector that apply would be shoving into the function really doesn't matter. All that matters is the index.
This question touches several points that are made in 'The R Inferno' http://www.burns-stat.com/pages/Tutor/R_inferno.pdf
There are some loops you should avoid, but not all of them. And using an apply function is more hiding the loop than avoiding it. This example seems like a good choice to leave in a 'for' loop.
Growing objects is generally bad form -- it can be extremely inefficient in some cases. If you are going to have a blanket rule, then "not growing objects" is a better one than "avoid loops".
You can create a list with the final length by:
result <- vector("list", ncol(g))
for(i in 1:ncol(g)) {
# stuff
result[[i]] <- #results
}
In some circumstances you might think the command:
window<-5
means give me a logical vector stating which values of 'window' are less than -5.
Spaces are good to use, mostly not to confuse humans, but to get the meaning directly above not to confuse R.
Using an apply function to do your regression is mostly a matter of preference in this case; it can handle some of the bookkeeping for you (and so possibly prevent errors) but won't speed up the code.
I would suggest using vectorized functions though to compute your first's and last's, though, perhaps something like:
window <- 5
ng <- 15 #or ncol(g)
xy <- data.frame(first = pmax( (1:ng) - window, 1 ),
last = pmin( (1:ng) + window, ng) )
Or be even smarter with
xy <- data.frame(first= c(rep(1, window), 1:(ng-window) ),
last = c((window+1):ng, rep(ng, window)) )
Then you could use this in a for loop like this:
results <- list()
for(i in 1:nrow(xy)) {
results[[i]] <- xy$first[i] : xy$last[i]
}
results
or with lapply like this:
results <- lapply(1:nrow(xy), function(i) {
xy$first[i] : xy$last[i]
})
where in both cases I just return the sequence between first and list; you would substitute with your actual regression code.