I'm using brute force right now..
x <- 1.03
Value <- c((1/x)^20,(1/x)^19,(1/x)^18,(1/x)^17,(1/x)^16,(1/x)^15,(1/x)^14,(1/x)^13,(1/x)^12,(1/x)^11,(1/x)^10,(1/x)^9,(1/x)^8,(1/x)^7,(1/x)^6,(1/x)^5,(1/x)^4,(1/x)^3,(1/x)^2,(1/x),1,x,x^2,x^3,x^4,x^5,x^6,x^7,x^8,x^9,x^10,x^11,x^12,x^13,x^14,x^15,x^16,x^17,x^18,x^19,x^20)
Value
but I would like to use an increment loop just like the for loop in java
for(integer I = 1; I<=20; I++)
^ is a vectorized function in R. That means you can simply use x^(-20:20).
Edit because this gets so many upvotes:
More precisely, both the base parameter and the exponent parameter are vectorized.
You can do this:
x <- 1:3
x^2
#[1] 1 4 9
and this:
2^x
#[1] 2 4 8
and even this:
x^x
#[1] 1 4 27
In the first two examples the length-one parameter gets recycled to match the length of the longer parameter. Thats why the following results in a warning:
y <- 1:2
x^y
#[1] 1 4 3
#Warning message:
# In x^y : longer object length is not a multiple of shorter object length
If you try something like that, you probably want what outer can give you:
outer(x, y, "^")
# [,1] [,2]
#[1,] 1 1
#[2,] 2 4
#[3,] 3 9
Roland already addressed the fact that you can do this vectorized, so I will focus on the loop part in cases where you are doing something more that is not vectorized.
A Java (and C, C++, etc.) style loop like you show is really just a while loop. Something that you would like to do as:
for(I=1, I<=20, I++) { ... }
is really just a different way to write:
I=1 # or better I <- 1
while( I <= 20 ) {
...
I <- I + 1
}
So you already have the tools to do that type of loop. However if you want to assign the results into a vector, matrix, array, list, etc. and each iteration is independent (does not rely on the previous computation) then it is usually easier, clearer, and overall better to use the lapply or sapply functions.
Related
I was prompted a question and am ever so close to solving what I need. The question is as follows-
"Write a while loop that computes and stores as a new object, the factorial of any non-negative integer mynum by decrementing mynum by 1 at each repetition of the braced code."
Another factor was that if 0 or 1 was entered, the output would be 1.
The code that I wrote as follows-
factorialcalc <- function(i){
factorial <- 1
if(i==0 | i==1){
factorial <- 1
} else{
while(i >= 1){
factorial <- factorial * i
i <- i-1
}
}
return (factorial)
}
with inputs-
mynum <- 5
factorialcalc(mynum)
and output-
[1] 120
You may be wondering, "your code works perfect, so what's the issue?"
My issue lies in the part of the question that says "computes AND stores."
How can I modify my code to put the answers of factorialcalc into a vector?
Example-
I input
mynum <- 5
factorialcalc(mynum)
and
mynum <- 3
factorialcalc(mynum)
and
mynum <- 4
factorialcalc(mynum)
When I call this new vector, I would like to see a vector with all three of their outputs
(so almost like I made a vector c(120,6,24))
I'm thinking there's a way to add this vector somewhere in my function or while loop, but I'm not sure where. Also, please note that the answer must contain a loop like in my code.
Option 1.
"Vectorize" your function
# simply wrap the whole thing in Vectorize()
Factorialcalc = Vectorize(function(i){
factorial <- 1
if(i==0 | i==1){
factorial <- 1
} else{
while(i >= 1){
factorial <- factorial * i
i <- i-1
}
}
return (factorial)
})
# Now when you supply it a vector, it runs on each element
> Factorialcalc(c(5, 3, 4))
[1] 120 6 24
Option 2.
Use functions that are designed to apply a single function to multiple elements of a supplied vector.
Using map_dbl from the purrr package, you can call:
map_dbl(c(5, 3, 4), factorialcalc)
Which supplies to your function factorialcalc each element in vector and concatenates each result before returning a vector.
Using base R you can simply use the apply-family functions:
sapply(c(5, 3, 4), factorialcalc)
and get the same result.
Example
> map_dbl(c(5, 3, 4), factorialcalc)
[1] 120 6 24
> sapply(c(5, 3, 4), factorialcalc)
[1] 120 6 24
Currently, I have
extract_modulo = function(x, n, fn=`[`) fn(x, (n-1L) %% length(x) + 1L)
`%[mod%` = function (x, n) extract_modulo(x, n)
And then:
seq(12) %[mod% 14
#[1] 2
Is this already built into R somewhere? I would think so, because R has several functions that recycle values (e.g., paste). However, I'm not finding anything with help('[['), ??index, or ??mod. I would think an R notation for this would be something like seq(12)[/14/] or as.list(seq(12))[[/14/]], for example.
rep_len() is a fast .Internal function, and appropriate for this use or when recycling arguments in your own function. For this particular case, where you're looking for the value at an index position beyond the length of a vector, rep_len(x, n)[n] will always do what you're looking for, for any nonnegative whole number 'n', and any non NULL x.
rep_len(seq(12), 14)[14]
# [1] 2
rep_len(letters, 125)[125]
# [1] "u"
And if it turns out you didn't need to recycle x, it works just as fine with an n value that is less than length(x)
rep_len(seq(12), 5)[5]
# [1] 5
rep_len(seq(12), 0)[0]
# integer(0)
# as would be expected, there is nothing there
You could of course create a wrapper if you'd like:
recycle_index <- function(x, n) rep_len(x, n)[n]
recycle_index(seq(12), 14)
# [1] 2
I have just started learning R and I wrote this code to learn on functions and loops.
squared<-function(x){
m<-c()
for(i in 1:x){
y<-i*i
c(m,y)
}
return (m)
}
squared(5)
NULL
Why does this return NULL. I want i*i values to append to the end of mand return a vector. Can someone please point out whats wrong with this code.
You haven't put anything inside m <- c() in your loop since you did not use an assignment. You are getting the following -
m <- c()
m
# NULL
You can change the function to return the desired values by assigning m in the loop.
squared <- function(x) {
m <- c()
for(i in 1:x) {
y <- i * i
m <- c(m, y)
}
return(m)
}
squared(5)
# [1] 1 4 9 16 25
But this is inefficient because we know the length of the resulting vector will be 5 (or x). So we want to allocate the memory first before looping. This will be the better way to use the for() loop.
squared <- function(x) {
m <- vector("integer", x)
for(i in seq_len(x)) {
m[i] <- i * i
}
m
}
squared(5)
# [1] 1 4 9 16 25
Also notice that I have removed return() from the second function. It is not necessary there, so it can be removed. It's a matter of personal preference to leave it in this situation. Sometimes it will be necessary, like in if() statements for example.
I know the question is about looping, but I also must mention that this can be done more efficiently with seven characters using the primitive ^, like this
(1:5)^2
# [1] 1 4 9 16 25
^ is a primitive function, which means the code is written entirely in C and will be the most efficient of these three methods
`^`
# function (e1, e2) .Primitive("^")
Here's a general approach:
# Create empty vector
vec <- c()
for(i in 1:10){
# Inside the loop, make one or elements to add to vector
new_elements <- i * 3
# Use 'c' to combine the existing vector with the new_elements
vec <- c(vec, new_elements)
}
vec
# [1] 3 6 9 12 15 18 21 24 27 30
If you happen to run out of memory (e.g. if your loop has a lot of iterations or vectors are large), you can try vector preallocation which will be more efficient. That's not usually necessary unless your vectors are particularly large though.
I have a function in R and I wish to take the sum of this function with different values. However, since I have a break condition (made by an if statement) I cannot just do this explicitly:
F<- function(x) if(x<5) 1 else 0
sum(F(seq(1,10,1))
#[1] 1
#Warning message:
#In if (x < 5) 1 else 0 :
# the condition has length > 1 and only the first element will be used
so it is trying to do the sequence of the function and not the sum of the sequence. I wish to avoid the for loop as this can make long codes very cluttered; specifically to avoid ugly nested for loops.
How do I go about this?
You can use Vectorize:
F_v <- Vectorize(F)
sum(F_v(seq(1,10,1)))
# [1] 4
If you like to avoid for-loops, sapply is an option for you, because it is faster.
sapply(seq(1,10,1), FUN <- function(x) {if(x<5) 1 else 0})
I would like to create a numeric vector with the results of a loop such as
> for (i in 1:5) print(i+1)
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
It seems strange that the same expression without 'print' returns nothing
> for (i in 1:5) i+1
>
Does anyone have an explanation/solution?
This is standard behaiviour -- when you say you want to create a numeric vector,
print will not do that
The expression in a for loop is an argument to the primitive function for
From ?`for` in the value section
for, while and repeat return NULL invisibly. for sets var to the last
used element of seq, or to NULL if it was of length zero.
print prints the results to the console.
for(i in 1:5) i + 1
merely calculates i + 1 for each iteration and returns nothing
If you want to assign something then assign it using <-, or less advisably assign
You can avoid an explicit loops by using sapply. This (should) avoid any pitfalls of growing vectors
results <- sapply(1:5, function(i) { i + 1})
Now frankly, there must be a better solution than this
loopee <- function(x){
res <- vector(mode = "numeric", length(x))
for (i in 1:x) {res[i] <- i+1}
return(res)}
> loopee(5)
[1] 2 3 4 5 6