How to combine a 'for' loop with an 'if' statement? - r

I am a newbie, and my question is probably the easiest many of you can imagine. Still, I am stuck, and been looking for answers everywhere, so please help. I am writing a simple loop, consisting of a 'for' and an 'if' statement, evaluating a simple vector. I keep getting wrong results and I do not know where the problem is. Here is the code:
Y <- c(3,5,2,7)
for (n in Y) {
if (n < 6) (Y[n]=0)
}
When evaluated, the result is: 3 0 0 7 0, which is NOT what I am expecting! The code is supposed to evaluate every item in Y and return 0 if it is less than 6. So it should be: 0 0 0 7. What am I doing wrong? Please help!

When you do for (n in Y) you are actually iterating over the elements of your array, so when you try to change the value of Y, you're not passing the index but are passing the value.
You need to do something like this (don't know which language you're using):
Y <- c(3,5,2,7)
for (n in 1:length(Y)) {
if (Y[n] < 6) (Y[n]=0)
}
With your original code what's happening is:
if (3 < 6) (Y[3]=0) --it changes position 3
if (5 < 6) (Y[5]=0) --it adds a 0 to position 5
if (2 < 6) (Y[2]=0) --it changes position 2
if (7 < 6) (Y[7]=0) --nothing happens

As R is a vectorized language, for loops are rarely needed, especially for basic operations. Getting acquainted with the vector features of R can save a lot of typing (and headaches). So, for replacing all values in Y which are less than 6 we can write
Y[Y < 6] <- 0
Y
[1] 0 0 0 7
Here, Y < 6 returns a logical vector of those elements of Y which fulfill the condition
[1] TRUE TRUE TRUE FALSE
and which are then used for subsetting.
Furthermore, R has the replace() function which can be used likewise:
replace(Y, Y < 6, 0)
[1] 0 0 0 7

Related

Removing elements that are multiples of 4 from a matrix in R

This code is supposed to remove all mutiples of 4 from the given vector, when I run it, only 8 gets removed.
multipleoffour<- function(y){
y2<-y
for (n in y )
{if (n%%4==0)
y2<-y2[-n]
}
return (y2)
}
multipleoffour(c(2,4,6,8,10,12,14))
Since R is vectorized this is more of an R way to do this:
multipleoffour<- function(y){
y[y %% 4 != 0]
}
multipleoffour(c(2,4,6,8,10,12,14))
## [1] 2 6 10 14
The reason why your code doesn't work is because y2<-y2[-n] remove the nth element of the vector and not n itself. In your example it removed 8, which is the 4th element of your vector. Otherwise, I agree with other answers about how to do it more efficiently.

Can't figure out how to format a for loop with if statements

I am in an intro to R course and the professor has not been much help. One of the questions on the latest homework has me stumped. The question is below, along with my answers so far.
8. [15 points] Given the following code,
#
# x <- rnorm(10)
#
# Do the following.
#
# (1) create a count vector named "count" of four elements and set each to 0 using the rep function.
# (2) using a for loop to process each value in the vector x, count how many times each of the following values occur in the vector x using an if statement.
# a. "value is between -1 and 1 inclusive"
# b. "value is between -2 and 2 inclusive, but not between -1 and 1",
# c. "value is between -3 and 3 inclusive, but not between -2 and -2", or
# d. "value is greater than 3 or less than -3".
# (3) print each of the four counts in the count vector using a while loop.
#
# For example, if the vector x contains the following ten values,
#
# 1.1478911 1.6183994 -2.3790632 -0.2566993 0.8923735
# -0.7523441 -0.7559083 0.9836396 1.0994189 2.5519972
#
# Then, the output should be as below.
#
# count[1] is 5
# count[2] is 3
# count[3] is 2
# count[4] is 0
x <- rnorm(10)
My answers:
(1) count <- c(rep(0,4))
(2)
for (count in x) {
if (x > -1 & x < 1) {
print(count[1])
}
I know there is something wrong with my code for part one but we haven't gone over anything like this in class and I have struggled to find a video for something like this. Please point me in the right direction and let me know what mistakes I have made, thanks so much!
You part one is correct. Maybe you can remove the initial c() from it.
x <- rnorm(10)
#Part 1
count <- rep(0,4)
#Part 2
for(i in x) {
if(i >= -1 && i <= 1)
count[1] <- count[1] + 1
else if(i >= -2 && i <= 2)
count[2] <- count[2] + 1
else if(i >= -3 & i <= 3)
count[3] <- count[3] + 1
else count[4] <- count[4] + 1
}
#Part 3
i <- 0
while (i < length(count)) {
i <- i + 1
print(sprintf('count[%d] is: %d', i, count[i]))
}
Note that there are better/efficient ways to do this but I think for the purpose of this exercise this is what your professor wants.
Each of the 4 slots in count is supposed to keep track of whether a value in x satisfies one of the 4 conditions listed (a. through d.).
If we were to speak it out loud, it'd go something like:
Look at element 1 in x (you can do that with x[1]). It's 1.1478911. This satisfies condition b., so add a 1 to the "b. counter", which is the second slot in count, or count[2].
Now look at element 2 in x (that's x[2])...(and so on, up to the last element in x).
To solve this task, you could just write out 10 statements, looking at each of the 10 elements in x separately, and update count on a case-by-case basis, but that is long and is hard to modify.
A for-loop is kind of like making a template for the spoken-out-loud part above. So instead of saying, "Ok, now we're on Element 3, let's see what the deal is", you can instead say, "Ok, now we're on Element i...", where i is just a temporary variable, a placeholder that only exists for the life of the for-loop. The i placeholder automatically takes on the value of the element in the vector we're iterating over.
If it's for (i in 1:3) then i will be 1, then 2, then 3.
If it's for (letter in c("a", "b", "c")), then letter will be "a", then "b", then "c".
So you can see that when you write for (count in x), that doesn't follow the rules of the for-loop. It's true that we'll want to update count at some point in the loop, but you've got it in the spot where our temporary placeholder is supposed to go. You can call that placeholder whatever you want, but i is common when looping over numbers, by convention.
Here's an example: the following code will start i at 1, and repeat the code inside the loop statement with new integers, until i gets to 10:
for (i in 1:10) {
print(paste("i is", i, "and the i'th value of x is", x[i]))
}
That should be enough to get you over the part you're stuck on.
A couple of additional hints:
f you want to know how many things are in a vector, such as x, you can use length(x) (try it, you will see the output is 10). So instead of doing: for(i in 1:10), you can swap out 10 for length(x).
count[3] <- count[3] + 1 adds 1 to whatever the current total is in the third element of count.
Good luck! Someone may post the answer to the whole problem, but if you want to work through each piece, I hope this is a good jump start for you.

Calculate a geometric progression

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.

Sum of functions in R

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})

Looping through selected values in R

I want to iterate a loop only for some values so I am using this:
present <- c(3,5,7,8)
for(i in present)
{
print(i)
}
which gives me
[1] 3
[1] 5
[1] 7
[1] 8
however I need to jump to the next value within the loop, say I dont want 5 to be printed in above example.
I cannot use next since I want it in nested for like this
present <- c(3,5,7,8)
for(i in present)
{
k <- i
"Jump to next value of present"
while(k < "The next value for i should come here")
{
k <- k + 1
print(k)
}
}
The output would be 3 4 5 6 7 8 but the condition must check value of k if it exceeds next value of i.
Is there anyway to accomplish this?
I'll take help of C to explain further,
for(i=0; i < 10; i++)
{
for(k=i;k <= i+1;k++)
{
printf("%d", k);
}
}
The link contains output of above code
http://codepad.org/relkenY3
It is easy in C since next value is in sequence, but here next value is not known, hence the problem.
What you should do is loop through two vectors:
x <- head(present, -1)
# [1] 3 5 7
y <- tail(present, -1)
# [1] 5 7 8
and the function to do that is mapply (have a look at ?mapply). A close translation of your pseudo-code would be:
invisible(mapply(function(x, y) while(x < y) {x <- x + 1; print(x)}, x, y))
but maybe you'll find this more interesting:
mapply(seq, x + 1, y)
I suspect the answer is to use seq_along and use it as an index into "present", but as others have pointed out your code does not promise to deliver what you expect, even with that simple modification. The K <- K=1 assignment jumps ahead too far to deliver a value of 3 at any point and the termination condition is likewise not clear. It turns into an infinite loop in the form you construct. Work with this;
present <- c(3,5,7,8)
for(i in seq_along(present))
{
k <- i
while(k < length(present) )
{
k <- k + 1
print(present[k])
}
}

Resources