get last repeat loop's result as vector in R - r

i want to create a vector of numbers (following weibulldistribution (shape=c,scale=b), the length is uncertain at the beginning of creating this vector (length depending on g)! using a function (c,b,g) with a repeat loop brings the result on screen, but not into the vector. So I need the last loop's result in a vector, but don't know how
t<-NULL
z<-NULL
p<-NULL
neededvector<-function(c,b,g) {
p<-repeat{
t<-rweibull(1,c,b)
append(z,t)
z<-print(append(z,t))
if(sum(((z*0.01)^2*pi)/4)>g)
break
}
}

Normally it's a bad idea to grow an object in a loop, since that's slow in R. If we knew your resulting vector were less than 1000, we could use cumsum to know when we should stop it:
neededvector <- function(c,b,g) {
z <- rweibull(1000, c, b)
z[((cumsum(z) * 0.01) ^ 2 * pi) <= g]
}
This solution won't work for you if the resulting vector should have been longer than 1000. But you can make it work, and be a lot faster than 1-at-a-time, by doing it in chunks.
neededvector <- function(c,b,g) {
z <- c()
while (TRUE) {
# generate values 1000 at a time
z <- c(z, rweibull(1000, c, b))
threshold <- ((cumsum(z) * 0.01) ^ 2 * pi) <= g
# check if this would include all elements of z.
# if not, return it.
if (sum(threshold) < length(z)) {
return(z[threshold])
}
}
}
Generally, rather than 1000, set that value to some length greater than you generally expect the Weibull to be. (If your vector ends up being length 100,000, this method will have poor performance unless you set it to create it in chunks closer to that length).

Related

Finding the value of infinite sums in r

I'm very new to r and programming so please stay with me :)
I am trying to use iterations to find the value of infinite iterations to the 4th decimal place. I.e. where the 4th decimal does not change. so 1.4223, where 3 does not change anymore so the result to 3 decimal place is 1.422.
The link above shows an example of a similar problem that I am faced with. My question is how do I create a for-loop that goes to infinity and find the value where the 4th decimal point stops changing?
I have tried using while loops but I am not sure how to stop it from just looping forever. I need some if statement like below:
result <- 0
i <- 1
d <- 1e-4
while(TRUE)
{
result <- result + (1/(i^2))
if(abs(result) < d)
{
break
}
i <- i + 1
}
result
Here's an example: to do the infinite loop, use while(TRUE) {}, and as you suggested use an if clause and break to stop when necessary.
## example equation shown
## fun <- function(x,n) {
## (x-1)^(2*n)/(n*(2*n-1))
## }
## do it for f(x)=1/x^2 instead
## doesn't have any x-dependence, but leave it in anyway
fun <- function(x,n) {
1/n^2
}
n <- 1
## x <- 0.6
tol <- 1e-4
ans <- 0
while (TRUE) {
next_term <- fun(x,n)
ans <- ans + next_term
if (abs(next_term)<tol) break
n <- n+1
}
When run this gives ans=1.635082, n=101.
R also has a rarely used repeat { } keyword, but while(TRUE) will probably be clearer to readers
there are more efficient ways to do this (i.e. calculating the numerator by multiplying it by (x-1)^2 each time)
it's generally a good idea to test for a maximum number of iterations as well so that you don't set up a truly infinite loop if your series doesn't converge or if you have a bug in your code
I haven't solved your exact problem (chose a smaller value of tol), but you should be able to adjust this to get an answer
as discussed in the answer to your previous question, this isn't guaranteed, but should generally be OK; you can check (I haven't) to be sure that the particular series you want to evaluate has well-behaved convergence

Lighten a fibonacci while loop

This problem has given headache for me and I just can't figure it out. The problem is to write R function which will return every Fibonacci number equal to or less than n.
So far I've tried to make while loop.
vast <- function(n) {
if (n==1) return(1)
x <- c(1,1)
while (length(x)-1 < n) {
pos <- length(x)
new <- x[pos-1] + x[pos]
x <- c(x,new)
}
x<-x[x <= n]
return(x)
}
It works like charm except when I try to return the work. At that point the R program starts infinite calculation and the course package jams.
The solution can be also written so that one makes assumption that n is an Fibonacci number. Is there any way to lighten this loop e.g. with break or next statements or would it be easier to approach the problem from different angle?
The code provides correct output as is, but it's very slow for large numbers. For instance, on my machine, vast(100000) (with only 25 elements in the result) takes over 10 seconds to run, and slows down exponentially after that.
The reason it's slow is that your while condition is testing if the vector that has n-1 elements, rather than the bare requirements of a vector whose last / largest vector is <= n. For the case of vast(100000), you are creating a 100,000-element vector, when the answer ultimately only needs the first 25 elements.
This code works instantaneously past n = 10^5000, whereas the original function gums up in the 100k's on my machine. The only change is that it is now checking to see if the last number in the vector is larger than n, not checking if the vector has n elements.
vast2 <- function(n) {
if (n==1) return(1)
x <- c(1,1)
# while (length(x)-1 < n) { # OLD
while (max(x) < n) { # NEW
pos <- length(x)
new <- x[pos-1] + x[pos]
x <- c(x,new)
}
x<-x[x <= n]
return(x)
}

Which loop to use, R language?

We have to create function(K) that returns vector which has all items smaller than or equal to K from fibonacci sequence. We can assume K is fibonacci item. For example if K is 3 the function would return vector (1,1,2,3).
In general, a for loop is used when you know how many iterations you need to do, and a while loop is used when you want to keep going until a condition is met.
For this case, it sounds like you get an input K and you want to keep going until you find a Fibonacci term > K, so use a while loop.
ans <- function(n) {
x <- c(1,1)
while (length(x) <= n) {
position <- length(x)
new <- x[position] + x[position-1]
x <- c(x,new)
}
return(x[x<=n])
}
`
Tried many different loops, and this is closest I get. It works with every other number but ans(3) gives 1,1,2 even though it should give 1,1,2,3. Couldn't see what is wrong with this.

Vectors & Ifelse Logic - Won't Populate Vector

I'm creating a function that takes two inputs: delta, and length. The function modifies an existing vector - let's call this vector base - by delta for 'length' specified elements.
I need to create a new vector, let's call it 'adjusted'. This vector, adjusted, needs to populate based on one condition: If the index value for the base vector is less than the length parameter specified in the function input, then I want to increase the base vector by delta for all elements less than length. All elements in the base vector greater than the specified length parameter are to remain the same as in base vector.
Here is an example of my code: I have tried to implement the logic in two ways.
1. Using an ifelse because it allows for vectorized output.
2. Using an if else logic.
adjusted <- vector() #initialize the vector.
#Create a function.
Adjustment <- function(delta, length) {
ifelse((index < length), (adjusted <- base + delta), (adjusted <- base))
head(adjusted)
}
#Method 2.
Adjustment <- function(delta, length) {
if (index < length) {
adjusted <- base + delta
}
else {adjusted <- base}
head(adjusted)
}
Where I am experiencing trouble is with my newly created vector, adjusted, will not populate. I'm not quite sure what is happening - I am very new to R and any insight would be much appreciated.
EDIT: With some advice given, I was able to return output. The only issue is that the 'adjusted' vector is now 2x the length of the index vector. I see that this is happening because there are two calculations, one in the if value is true, and one in the if value is false. However, I want the function to write to the vector adjusted only in the elements for which the index is less than the parameter length.
For example. Let's say that the index vector is 10. If I set length to 3, I want adjusted to reflect a change for elements 1:3 and the same information in base for 4:10.
My code reflects adjusted is now length 20. How can I approach this and maintain the original value of the vector?
adjusted <- c()
Adjustment <- function(delta, length) {
ifelse(index < length, adjusted <<- c(adjusted, base + delta), adjusted <<- c(adjusted, base))
head(adjusted)
}
How about using a bit of Boolean algebra:
adjusted <- base + delta*(base > length)
Adjustment <- function(delta, length) {
if (index < length) {
for(i in 1:length-1){
adjusted[i] <- base[i] + delta
}
}
else {adjusted <- base}
head(adjusted)
}
index=2
length=5
base <- c(1,2,3,4,5,6,7,8,9,10)
delta = 2
Adjustment(delta,length)
This returns a vector that has all values < indexVALUE from base vector added by delta.

Logical comparison of two vectors with binary (0/1) result

For an assignment I had to create a random vector theta, a vector p containing for each element of theta the associated probability, and another random vector u. No problems thus far, but I'm stuck with the next instruction which I report below:
Generate a vector r1 that has a 1 in position i if pi ≥ ui and 0 if pi < ui. The
vector r1 is a Rasch item given the latent variable theta.
theta=rnorm(1000,0,1)
p=(exp(theta-1))/(1+exp(theta-1))
u=runif(1000,0,1)
I tried the following code, but it doesn't work.
r1<-for(i in 1:1000){
if(p[i]<u[i]){
return("0")
} else {
return("1")}
}
You can use the ifelse function:
r1 <- ifelse(p >= u, 1, 0)
Or you can simply convert the logical comparison into a numeric vector, which turns TRUE into 1 and FALSE into 0:
r1 <- as.numeric(p >= u)
#DavidRobinson gave a nice working solution, but let's look at why your attempt didn't work:
r1<-for(i in 1:1000){
if(p[i]<u[i]){
return("0")
} else {
return("1")}
}
We've got a few problems, biggest of which is that you're confusing for loops with general functions, both by assigning and using return(). return() is used when you are writing your own function, with function() <- .... Inside a for loop it isn't needed. A for loop just runs the code inside it a certain number of times, it can't return something like a function.
You do need a way to store your results. This is best done by pre-allocating a results vector, and then filling it inside the for loop.
r1 <- rep(NA, length(p)) # create a vector as long as p
for (i in 1:1000) {
if (p[i] < u[i]) { # compare the ith element of p and u
r1[i] <- 0 # put the answer in the ith element of r1
} else {
r1[i] <- 1
}
}
We could simplify this a bit. Rather than bothering with the if and the else, you could start r1 as all 0's, and then only change it to a 1 if p[i] >= u[i]. Just to be safe I think it's better to make the for statement something like for (i in 1:length(p)), or best yet for (i in seq_along(p)), but the beauty of R is how few for loops are necessary, and #DavidRobinson's vectorized suggestions are far cleaner.

Resources