This question already has an answer here:
Why does the vector gets expanded in the loop
(1 answer)
Closed 6 years ago.
I am running into some behaviour with R that I find confusing. Does anyone have any insight into what is going on here?
Define two objects
i <- 5
nr <- 10
So i + 2 and nr + 1
> i+2
[1] 7
> nr+1
[1] 11
So to create a sequence from 7 to 11 I could do this:
7:11
But my question why does this not produce the same result?
i+2:nr+1
We already established above that it's input numbers are equivalent. Obviously I'm missing something here but I just don't know what it is.
You have just discovered the prime R gotcha, namely: 1:n-1 produces the sequence 0, 1, 2, ..., n-1.
To obtain what you desire, wrap the expressions in brackets:
1:(n-1)
or use
seq.int(1, n-1)
The reason for the issue is operator precedence - ?Syntax`
Related
This question already has answers here:
Sample from vector of varying length (including 1)
(4 answers)
Closed 3 years ago.
sample(x,n) The parameters are the vector, and how many times you wish to sample
sample(c(5,9),1) returns either 5 or 9
however,
sample(5,1) returns 1,2,3,4, or 5?
I've read the help section:
If x has length 1, is numeric (in the sense of is.numeric) and x >= 1,
sampling via sample takes place from 1:x. Note that this convenience
feature may lead to undesired behaviour when x is of varying length in
calls such as sample(x). See the examples.
But is there a way to make it not do this? Or do I just need to include an if statement to avoid this.
Or do I just need to include an if statement to avoid this.
Yeah, unfortunately. Something like this:
result = if(length(x) == 1) {x} else {sample(x, ...)}
Here's an alternative approach: you simply subset a random value from your vector like this -
set.seed(4)
x <- c(5,9)
x[sample(length(x), 1)]
[1] 9
x <- 5
x[sample(length(x), 1)]
[1] 5
This question already has an answer here:
Order of operator precedence when using ":" (the colon)
(1 answer)
Closed 4 years ago.
I have a vector and would like to extract element 3 and 4. Can you please help me understand what the logic is behind the code version without parenthesis? I appreciate your help.
a=c(1:5)
a[(2+1): 4] # with parenthesis, makes sense
[1] 3 4
a[ 2+1 : 4] # without parenthesis, what is the logic here?
[1] 3 4 5 NA
The : operator is evaluated before the + operator.
Consider
print(c(2+1:4))
This returns
[1] 3 4 5 6
Because a vector 1,2,3,4 is created, then all elements are added by 2.
R Operator Syntax and Precedence
gives an overview over the priority of R's operators. The sequence operator : comes before the arithmetic operators like + or -.
so I have a loop that finds the position in the matrix where there is the largest difference in consecutive elements. For example, if thematrix[8] and thematrix[9] have the largest difference between any two consecutive elements, the number given should be 8.
I made the loop in a way that it will ignore comparisons where one of the elements is NaN (because I have some of those in my data). The loop I made looks like this.
thenumber = 0 #will store the difference
for (i in 1:nrow(thematrix) - 1) {
if (!is.na(thematrix[i]) & !is.na(thematrix[i + 1])) {
if (abs(thematrix[i] - thematrix[i + 1]) > thenumber) {
thenumber = i
}
}
}
This looks like it should work but whenever I run it
Error in if (!is.na(thematrix[i]) & !is.na(thematrix[i + 1])) { :
argument is of length zero
I tried this thing but with a random number in the brackets instead of i and it works. For some reason it only doesn't work when I use the i specified in the beginning of the for-loop. It doesn't recognize that i represents a number. Why doesn't R recognize i?
Also, if there's a better way to do this task I'd appreciate it greatly if you could explain it to me
You are pretty close but when you call i in 1:nrow(thematrix) - 1 R evaluates this to make i = 0 which is what causes this issue. I would suggest either calling i in 1:nrow(thematrix) or i in 2:nrow(thematrix) - 1 to start your loop at i = 1. I think your approach is generally pretty intuitive but one suggestion would be to frequently use the print() function to evaluate how i changes over the course of your function.
The issue is that the : operator has higher precedence than -; you just need to use parentheses around (nrow(thematrix)-1). For example,
thematrix <- matrix(1:10, nrow = 5)
##
wrong <- 1:nrow(thematrix) - 1
right <- 1:(nrow(thematrix) - 1)
##
R> wrong
#[1] 0 1 2 3 4
R> right
#[1] 1 2 3 4
Where the error message is coming from trying to access the zero-th element of thematrix:
R> thematrix[0]
integer(0)
The other two answers address your question directly, but I must say this is about the worst possible way to solve this problem in R.
set.seed(1) # for reproducible example
x <- sample(1:10,10) # numbers 1:10 in random order
x
# [1] 3 4 5 7 2 8 9 6 10 1
which.max(abs(diff(x)))
# [1] 9
The diff(...) function calculates sequential differences, and which.max(...) identifies the element number of the maximum value in a vector.
This question already has answers here:
Dynamic variables in base R
(4 answers)
Closed 8 years ago.
I'm not a developer, and I can't express well what I need in simple words. It is connected to things like environments, scoping, enclosure, and perhaps pointers and references.
It should be clear with code:
a<-c(1,2)
b<-length(a)
a<-c(1,2,3)
b
[1] 2
I want b to return 3.
What do I change in the second line? Is it possible to do it without defining new custom functions and using external packages?
Failed trying eval, assign, <<- so far
I'm not recommending that you should actually use it, but makeActiveBinding() will do what you're asking for:
makeActiveBinding("b", function() length(a), .GlobalEnv)
a <- c(1,2)
b
# [1] 2
a <- c(1,2,4)
b
# [1] 3
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to generate a vector containing a numeric sequence?
In R, how can I get the list of numbers from 1 to 100? Other languages have a function 'range' to do this. R's range does something else entirely.
> range(1,100)
[1] 1 100
Your mistake is looking for range, which gives you the range of a vector, for example:
range(c(10, -5, 100))
gives
-5 100
Instead, look at the : operator to give sequences (with a step size of one):
1:100
or you can use the seq function to have a bit more control. For example,
##Step size of 2
seq(1, 100, by=2)
or
##length.out: desired length of the sequence
seq(1, 100, length.out=5)
If you need the construct for a quick example to play with, use the : operator.
But if you are creating a vector/range of numbers dynamically, then use seq() instead.
Let's say you are creating the vector/range of numbers from a to b with a:b, and you expect it to be an increasing series. Then, if b is evaluated to be less than a, you will get a decreasing sequence but you will never be notified about it, and your program will continue to execute with the wrong kind of input.
In this case, if you use seq(), you can set the sign of the by argument to match the direction of your sequence, and an error will be raised if they do not match. For example,
seq(a, b, -1)
will raise an error for a=2, b=6, because the coder expected a decreasing sequence.