New to R here and trying to place a function in a for loop. The function works and the for loop worked when I had another function in it, but when I put them together I am getting the error "missing value where TRUE/FALSE needed" when I didn't need one before. The function I have is :
roll <- function(){
die<- 1:20 # 20 sided die
dice <- sample(die, 2, replace=TRUE) # Roll the die twice
sum(dice) # Add results
}
and I am trying to get it to run 100+ times while putting the output in a matrix. Maybe I am just not quite grasping the problem with the for loop but I have it as such:
for(i in 1:nrolls) { #nrolls=100
roll <- sample(die)
if(roll[i] >= 25) {
G_than <- 1
} else{
L_than <- 1
}
}
Any help would be appreciated!
For loop aren't what you should use in that case.
Simply use sapply if you want to get the result in a vector like this:
roll <- function(x){
die<- 1:20 # 20 sided die
dice <- sample(die, 2, replace=TRUE) # Roll the die twice
sum(dice) # Add results
}
sapply(c(1:100), roll)
Note that sapply will send the argument to the function, so you need to change roll to get that input (and do nothing with it)
Related
I am working out with a data in R.
a<-rep(NA,400)
for(i in 1:10){for(j in 0:40){print(dat$V2[i]-j)}}
Instead of printing, I want to add that value into an empty array (a). I would be thankful if someone help me with the same.
In a case like this (nested loops), often the easiest way is to add a counter to keep track of positions in the array:
a <- rep(NA, 400)
counter <- 1
for(i in 1:10){
for(j in 0:40){
a[counter] <- dat$V2[i]-j
counter <- counter + 1
}
}
Here is one way:
#a<-rep(NA,400)
#for(i in 1:10){for(j in 0:40){print(dat$V2[i]-j)}}
a <- as.numeric( sapply( 1:10, function(i){
sapply( 0:40, function(j) {
dat$V2[i]-j
})
}))
sapply is useful here because countrary to a for loop it returns something with each loop. So in this case I first loop over 1:10, like your for loop, with the useful difference that it actually returns something each time.
What it does in each iteration is to run a new nested block, also using sapply, this time looping over 0:40, also this time returning something, this time its the expression you have innermost in your for loop.
So for 10 times, for each of 1:10, it will loop over 0:40, each time calculating your expression and returning it, which should result in it getting calculated and returned as you want.
as.numeric is wrapped around it to make sure it stays as one long vector, which seems to be what you want.
A way only using loops:
for(i in 1:10){
for(j in 0:39){
print(i*40 - 39 + j)
a[i*40 - 39 + j] = dat$V2[i]-j}}
PS: as you want to create a vector with 400 observations, and i goes from 1 to 10, j needs to have "length" 40, so you want it to be 0:39.
When you want to create a vector (1 dimentional) with a doble loop, the following formula normally applies:
index of the vector = i*length(j) - (length(j)-1) + j
My original function embodies several optimize() functions, for which I get different results when I apply the function the first time vs. second time.
I tried this but I made sure that the returned value is one-dimensional.
fn = function(A,P){
l_fn = function(x) {
L <- x[1]
-((A*L*P)-(P*L^2)) # -1 because optimize-function finds minimum
}
l_opt <- as.numeric(optimize(l_fn,c(0,1000))[2]) # get objective output
return(l_opt)
}
f <- data.frame(x=c(10:20))
for (i in 1:length(f)) { # run this part 2 times!
f$test <- sin(f$x) # this is how I expect a function to behave
f$out[i] <- fn(f$x[i],100)
}
running the code the first time produces f$out that are all equal (weird). running the for loop again changes f$out, eventhough the input parameters remain the same! How is that possible?
Suppose I have a function which returns me a list of output. How could I call a specific output at once? My original function is difficult and must return my output as a list. Sometimes I need to look at a special output (3 or 5 of them (out of 10). How can I do that very quickly using a shortcut code instead of repeating it several times to get one output each time?
For example,
x <- rnorm(1:5)
y <- rnorm(1:5)
myfun <- function(x,y){
mult <- sumf <- distfu <- list()
for(i in 1:5){
mult[[i]] <- x[[i]]*y[[i]]
sumf[[i]] <- x[[i]]+y[[i]]
distfu[[i]] <- x[[i]]-y[[i]]
}
out <- list()
out$mult <- mult
out$sumf <- sumf
out$distf <- distfu
return(out)
}
myres <- myfun(x,y)
How can I call myres$multand
myres$distf only at one time?
I tried this: myres$[c(1,3)] but it was wrong.
Please note that this example is simple, however, my function returns more than 10 outputs. So, if I need to only look at 5 of them, then I need to repeat this myfun$.. five times. I just would like to know if there is a way to call all the 5 outputs at once`.
To call a specific elements of a list you must do it like this:
myres[c(1,3)]
In your code there was a typo $ after myres
I hope this will help you.
I am aware this is a very basic question and am sorry to take up everyone's time. I created a function but would like to take those results, and apply it to the function again ( I am trying to model growth).
I don't think I want to use a loop because I need the values to come from the function. I also don't think it's apply because I need to extract the values from the function.
Here is my function
initial<-c(36.49)
second<-NULL
growth <- function(x){
second <- (131.35-(131.35 -x)*exp(-0.087))
}
second<-growth(initial)
third<-growth(second)
fourth<-growth(third)
fifth<-growth(fourth)
sixth<-growth(fifth)
seventh<-growth(sixth)
here is how I am doing it now, but as you can see I would have to keep doing this over and over again
You can use loop. Just store the outputs in a vector:
# initial value
initial<-c(36.49)
# dont need this i think
# second<-NULL
# create a holding vector fro result
values <- vector()
# assign
values[1] <- initial
# your function
growth <- function(x){
second <- (131.35-(131.35 -x)*exp(-0.087))
}
# start a loop; you start with 2
for(i in 2:7){
# then access the previous value using i - 1
# then store to the next index, which is i
values[i] <- growth(values[i - 1])
}
This should do the same.
Something along the lines of this maybe can help
x <- 1
try <- function(x) x <<- x+1
for(i in 1:5) try(x)
I am having trouble optimising a piece of R code. The following example code should illustrate my optimisation problem:
Some initialisations and a function definition:
a <- c(10,20,30,40,50,60,70,80)
b <- c(“a”,”b”,”c”,”d”,”z”,”g”,”h”,”r”)
c <- c(1,2,3,4,5,6,7,8)
myframe <- data.frame(a,b,c)
values <- vector(length=columns)
solution <- matrix(nrow=nrow(myframe),ncol=columns+3)
myfunction <- function(frame,columns){
athing = 0
if(columns == 5){
athing = 100
}
else{
athing = 1000
}
value[colums+1] = athing
return(value)}
The problematic for-loop looks like this:
columns = 6
for(i in 1:nrow(myframe){
values <- myfunction(as.matrix(myframe[i,]), columns)
values[columns+2] = i
values[columns+3] = myframe[i,3]
#more columns added with simple operations (i.e. sum)
solution <- rbind(solution,values)
#solution is a large matrix from outside the for-loop
}
The problem seems to be the rbind function. I frequently get error messages regarding the size of solution which seems to be to large after a while (more than 50 MB).
I want to replace this loop and the rbind with a list and lapply and/or foreach. I have started with converting myframeto a list.
myframe_list <- lapply(seq_len(nrow(myframe)), function(i) myframe[i,])
I have not really come further than this, although I tried applying this very good introduction to parallel processing.
How do I have to reconstruct the for-loop without having to change myfunction? Obviously I am open to different solutions...
Edit: This problem seems to be straight from the 2nd circle of hell from the R Inferno. Any suggestions?
The reason that using rbind in a loop like this is bad practice, is that in each iteration you enlarge your solution data frame and then copy it to a new object, which is a very slow process and can also lead to memory problems. One way around this is to create a list, whose ith component will store the output of the ith loop iteration. The final step is to call rbind on that list (just once at the end). This will look something like
my.list <- vector("list", nrow(myframe))
for(i in 1:nrow(myframe)){
# Call all necessary commands to create values
my.list[[i]] <- values
}
solution <- rbind(solution, do.call(rbind, my.list))
A bit to long for comment, so I put it here:
If columns is known in advance:
myfunction <- function(frame){
athing = 0
if(columns == 5){
athing = 100
}
else{
athing = 1000
}
value[colums+1] = athing
return(value)}
apply(myframe, 2, myfunction)
If columns is not given via environment, you can use:
apply(myframe, 2, myfunction, columns) with your original myfunction definition.