Reputation:
I have two lists, each list contains two vectors i.e,
x <- list(c(1,2),c(3,4))
y <- list(c(2,4),c(5,6))
z <- list(c(0,0),c(1,1), c(2,3),c(4,5))
I would like to use for
loop to iterate over the first list and if
statement for the second list as follows:
for (j in 1:seq(x)){
if(y[[j]] == c(2,4))
z[[j]] <- c(0,0)
}
I would like to iterate over the first list and for each iteration I would like to give a condition for the second list. My function is complex, so I upload this example which is similar to what I am trying to do with my original function. So that is, I would like to choose the values of z
based on the values of y
. For x
I just want to run the code based on the length of x
.
When I run it, I got this message:
Warning messages:
1: In 1:seq(x) : numerical expression has 2 elements: only the first used
2: In if (y[[j]] == c(2, 4)) y[[j]] <- c(0, 0) :
the condition has length > 1 and only the first element will be used
I search this website and I saw similar question but it is not helpful (if loop inside a for loop which iterates over a list in R?). This question is just for the first part my question. So, it does not help me with my problem.
any help please?
Upvotes: 0
Views: 91
Reputation: 1
For the first part, seq()
will returns [1] 1 2
. So, you need to use j in seq(x)
or j in 1:length(x)
.
and for the second part, as the command you used generates TRUE
and FALSE
as many as the elements in the vectors, you can use setequal(x,y)
. This command will check whether two objects are equal or not. two objects can be vectors, dataframes, etc, and the result is TRUE
or FALSE
.
The final code can be:
for (j in 1:length(x)){
if (setequal(y[[j]], c(2,4)) == TRUE) {
z[[j]] <- c(0,0)
}
}
or:
for (j in seq(x)){
if (setequal(y[[j]], c(2,4)) == TRUE) {
z[[j]] <- c(0,0)
}
}
Upvotes: 0
Reputation: 6813
The first warning is caused by using seq()
which returns a [1] 1 2
in combination with the colon operator which creates a sequence between the LHS and RHS. Both values on the left and right of the colon must be of length 1. Otherwise it will take the first element and discard the rest. So 1:seq(x)
is the same as writing 1:1
The second warning is that the if
statement gets 2 logical values from your condition:
y[[1]] == c(2, 4)
[1] TRUE TRUE
If you want to test if elements of the vector are the same you can use your notation. If you want to test if the vectors are the same, you can use all.equal
.
isTRUE(all.equal(y[[1]], c(2,4)))
[1] TRUE
It returns TRUE
if vectors are equal (but not FALSE
if they are not, which is why it needs to be used along with isTRUE()
).
To get rid of the warnings, you can do:
for (j in seq_along(x)){
if (isTRUE(all.equal(y[[j]], c(2,4)))) {
z[[j]] <- c(0,0)
}
}
Note: seq_along()
is a fast primitive for seq()
Upvotes: 4