FOR loop in R; not getting what I want - r

Just a general question:
When I run:
ok<-NULL
for (i in 1:3) {
ok[i]=i^2
i=i+1
}
The loop works (as expected).
> ok
[1] 1 4 9
Now when I try to do something like:
ok<-NULL
for (i in 1:3) {
ok[i]=i^2
x[i]<-ok[i]+1
y[i]<-cbind(ok[i],x)
i=i+1
}
And I want:
y = 1
2
4
5
9
10
Instead I get:
Warning messages:
1: In y[i] <- rbind(ok[i], x) :
number of items to replace is not a multiple of replacement length
2: In y[i] <- rbind(ok[i], x) :
number of items to replace is not a multiple of replacement length
3: In y[i] <- rbind(ok[i], x) :
number of items to replace is not a multiple of replacement length
4: In y[i] <- rbind(ok[i], x) :
number of items to replace is not a multiple of replacement length
5: In y[i] <- rbind(ok[i], x) :
number of items to replace is not a multiple of replacement length
Thanks in advance.

You should read up on R basics before starting to program.
You don't have to increment i in the loop (actually its quite confusing).
You don't cbind or rbind vectors this is for data.frame columns and rows.
y <- NULL
for(i in 1:3){ ok <- i^2; x <- ok + 1; y <- c(y, ok, x) }
or:
as.vector(sapply(1:3, function(i){ ok <- i^2; x <- ok + 1; c(ok, x) }))

With this command y[i]<-cbind(ok[i],x) you attempt to replace one element in the vector with several. This causes an error.

If you want to to get 1:3 squared, you would use:
ok <- (1:3)^2
ok
# [1] 1 4 9
If you want to get 1:3 squared, along with the numbers right after them, you might try:
as.vector(rbind(ok, ok+1))
[1] 1 2 4 5 9 10
for loops in R are often the wrong solution to your problem.

Related

About missing value where TRUE/FALSE needed in R

I want to return the number of times in string vector v that the element at the next successive index has more characters than the current index.
Here's my code
BiggerPairs <- function (v) {
numberOfTimes <- 0
for (i in 1:length(v)) {
if((nchar(v[i+1])) > (nchar(v[i]))) {
numberOfTimes <- numberOfTimes + 1
}
}
return(numberOfTimes)
}
}
missing value where TRUE/FALSE needed.
I do not know why this happens.
The error you are getting is saying that your code is trying to evaluate a missing value (NA) where it expects a number. There are likely one of two reasons for this.
You have NA's in your vector v (I suspect this is not the actual issue)
The loop you wrote is from 1:length(v), however, on the last iteration, this will try the loop to try to compare v[n+1] > v[n]. There is no v[n+1], thus this is a missing value and you get an error.
To remove NAs, try the following code:
v <- na.omit(v)
To improve your loop, try the following code:
for(i in 1:(length(v) -1)) {
if(nchar(v[i + 1]) > nchar(v[i])) {
numberOfTimes <- numberOfTimes + 1
}
}
Here is some example dummy code.
# create random 15 numbers
set.seed(1)
v <- rnorm(15)
# accessing the 16th element produces an NA
v[16]
#[1] NA
# if we add an NA and try to do a comparison, we get an error
v[10] <- NA
v[10] > v[9]
#[1] NA
# if we remove NAs and limit our loop to N-1, we should get a fair comparison
v <- na.omit(v)
numberOfTimes <- 0
for(i in 1:(length(v) -1)) {
if(nchar(v[i + 1]) > nchar(v[i])) {
numberOfTimes <- numberOfTimes + 1
}
}
numberOfTimes
#[1] 5
Is this what you're after? I don't think there is any need for a for loop.
I'm generating some sample data, since you don't provide any.
# Generate some sample data
set.seed(2017);
v <- sapply(sample(30, 10), function(x)
paste(sample(letters, x, replace = T), collapse = ""))
v;
#[1] "raalmkksyvqjytfxqibgwaifxqdc" "enopfcznbrutnwjq"
#[3] "thfzoxgjptsmec" "qrzrdwzj"
#[5] "knkydwnxgfdejcwqnovdv" "fxexzbfpampbadbyeypk"
#[7] "c" "jiukokceniv"
#[9] "qpfifsftlflxwgfhfbzzszl" "foltth"
The following vector marks the positions with 1 in v where entries have more characters than the previous entry.
# The following vector has the same length as v and
# returns 1 at the index position i where
# nchar(v[i]) > nchar(v[i-1])
idx <- c(0, diff(nchar(v)) > 0);
idx;
# [1] 0 0 0 0 1 0 0 1 1 0
If you're just interested in whether there is any entry with more characters than the previous entry, you can do this:
# If you just want to test if there is any position where
# nchar(v[i+1]) > nchar(v[i]) you can do
any(idx == 1);
#[1] TRUE
Or count the number of occurrences:
sum(idx);
#[1] 3

R programming language LOOPS

y <- vector()
i <- 5
while((2<3)<i){
y[i] <- "Hello World!"
i <- i-1 }
y
So I didn't understand how to while loop works when while((2<3)<i) is the case, 2<3 is true for all conditions and i end up with TRUE<i, what does this mean? Or am I thinking wrong?
I just didn't get how to condition of the while loop works, if I get that I believe I will work it out.
Also another question:
xxx <- function(vec){
n <- length(vec)
}
for(i in 1:n){
x <- vec[i]
if (vec[i]<x){
x <- vec[i]
}
} return(x)
This xxx function is suppose to output the minimum value of the function? okay i see but how?
when we enter the loop we first do x<- vec[i] without doing this we can't pass to the next command the if statement right? so since we do x <- vec[i] earlier if command won't work probably since x==vec[i] all the time.
Please help guys since iI have the exam tomorrow :(
1) ?Comparison says, referring to the two arguments of any comparison operator such as < :
If the two arguments are atomic vectors of different types, one is
coerced to the type of the other, the (decreasing) order of precedence
being character, complex, numeric, integer, logical and raw.
so in this case we have one logical argument and one numeric argument so the the logical argument is coerced to numeric (where FALSE is converted to 0 and TRUE is converted to 1). Thus (2<3)<5 is the same as TRUE < 5 which is the same as 1 < 5 which is TRUE:
(2<3)<5
## [1] TRUE
2) For xxx you probably want this:
xxx <- function(vec) {
x <- Inf
for(i in seq_along(vec)) if (vec[i] < x) x <- vec[i]
x
}
The first statement in the body assigns Inf to x In the second statement in the body seq_along(vec) is 1, 2, ..., length(vec) so the for loop iterates i over 1, 2, ..., length(vec) with each iteration replacing x with vec[i] if vec[i] is less than x. Note that if vec has zero length then the loop is not run at all since seq_along(vec) has zero length.
Testing it out:
> xxx(1:3)
[1] 1
> xxx(3:1)
[1] 1
> xxx(numeric(0)) # zero length input
Inf
Of course R already has the min function which does the same thing.

R: Summing the even terms in a Fibonacci Sequence with warnings

I've been set a question on the Fibonacci Sequence and although I've been successful in doing the sequence, I haven't been as lucky summing the even terms up (i.e. 2nd, 4th, 6th... etc.) My code is below as well as the part of the question I am stuck on. Any guidance would be brilliant!
Question:
Write a function which will take as an input x and y and will return either the sum of the first x even Fibonacci numbers or the sum of even Fibonacci numbers less than y.
That means the user will be able to specify either x or y but not both.
You have to return a warning if someone uses both numbers (decide
on the message to return)
Code:
y <- 10
fibvals <- numeric(y)
fibvals[1] <- 1
fibvals[2] <- 1
for (i in 3:y) {
fibvals[i] <- fibvals[i-1]+fibvals[i-2]
if (i %% 2)
v<-sum(fibvals[i])
}
v
To get you started since this sounds like an exercise.
I would split your loop up into steps rather than do the summing within the loop with an if statement. Since you already have the sequence code working, you can just return what is asked for by the user. The missing function would probably help you out here
f <- function(x, y) {
if (missing(y)) {
warning('you must give y')
y <- 10
}
fibvals <- numeric(y)
fibvals[1] <- 1
fibvals[2] <- 1
for (i in 3:y) {
fibvals[i] <- fibvals[i-1]+fibvals[i-2]
}
evens <- fibvals %% 2 == 0
odds <- fibvals %% 2 != 0
if (missing(x)) {
return(sum(fibvals[evens]))
} else return(fibvals)
}
f(y = 20)
# [1] 3382
f(10)
# [1] 1 1 2 3 5 8 13 21 34 55
# Warning message:
# In f(10) : you must give y

Select a column of matrix in r by looping

I have a matrix:
mvn.var=matrix(c(3,1,1,4,6,7,8,9),4,2,byrow=T)
And I try
for (i in 1:dim(mvn.var)[2]) {
y[i]=mvn.var[,i]
}
Because I want to have vectors y[i] where y[i] is a vector that consists of the elements of the i-th column of the previous mvn.var matrix.
I get:
Warning messages:
1: In y[i] = mvn.var[, i] :
number of items to replace is not a multiple of replacement length
2: In y[i] = mvn.var[, i] :
number of items to replace is not a multiple of replacement length
You are trying to assign to an element of the vector. Try this instead,
mvn.var=matrix(c(3,1,1,4,6,7,8,9),4,2,byrow=T)
y = matrix(data=NA,2,4,byrow=T)
for (i in 1:dim(mvn.var)[2]) {
y[i,]=mvn.var[,i]
}
However you can achieve the same result by merely transposing your matrix, e.g., t(mvn.var).
You try to put a vector of length 4 into something of length 1 (=i'th element of y). The message warns you, because y[i] will only contain the first element of the column.
Try making y a list:
mvn.var=matrix(c(3,1,1,4,6,7,8,9),4,2,byrow=T)
y <- list()
for (i in 1:dim(mvn.var)[2])
y[[i]]=mvn.var[,i]
y
# [[1]]
# [1] 3 1 6 8
#
# [[2]]
# [1] 1 4 7 9

append results of loop into numeric vector

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

Resources